本文主要介绍一下通过react实现一个简单的代办事件列表。
本文主要是记录一下实现过程以及后续改进方向。项目具体源码见仓库:gitee.com/piao-chen/r...
项目搭建
使用react脚手架进行搭建。首先运行命令:npm install -g create-react-app
进行安装react脚手架。安装成功后,使用create-react-app XXX
进行创建项目。
项目创建后的目录结构如下:
由于本项目要求十分简单,就不再拆分组件了,直接书写在App.js中。全局样式书写在index.css中,App.css中书写App组件的样式。
具体代码分析
页面结构
jsx
<div>
<div>
<header>
<span>待办事项</span>
</header>
<section>
{
list.length === 0
? <span className='no-data'>暂无数据</span>
:
<ul>
{
list.map(item => {
return (
<li key={item.id}>
<div></div>
<span>{item.thing}</span>
<button>
编辑
</button>
<button>
点击完成
</button>
</li>
)
})
}
</ul>
}
</section>
<footer>
<button>{'+ 添加事项'}</button>
</footer>
</div>
</div>
上面为待办列表的html结构,使用了语义化结构,也是对前面的语义化结构知识的一些复习。整体分为三个部分,分别为标题区域,列表主体区域以及底部添加待办区域。
样式添加
下面是index.css全局样式:
css
* {
margin: 0;
padding: 0;
}
html,
body{
width: 100%;
height: 100%;
}
#root{
width: 100%;
height: 100%;
background-color: antiquewhite;
}
/* 我觉得原生滚动条不好看 自定义一下滚动条 */
/* 滚动条整体部分 */
::-webkit-scrollbar {
width: 8px;
height: 6px;
}
/* 滚动条上方按钮 */
::-webkit-scrollbar-button {
display: none;
}
/* 滚动条滑块 */
::-webkit-scrollbar-thumb {
background-color: rgb(191, 190, 190);
border-radius: 10px;
}
/* 滚动条轨道 */
::-webkit-scrollbar-track {
background-color: transparent;
}
App.css样式如下:
css
.main-container{
display: flex;
height: 100%;
width: 100%;
justify-content: center;
align-items: center;
}
.main-wrap{
width: 40%;
height: 90%;
background-color: #fff;
border-radius: 10px;
}
.note-title{
display: flex;
justify-content: center;
align-items: center;
height: 10%;
width: 100%;
color: #fff;
background-color: #008cff;
line-height: 100%;
font-weight: 600;
font-size: 32px;
font-family: '方正姚体';
}
.item-body{
width: 100%;
height: 75%;
overflow: auto;
}
.item-container{
width: 100%;
min-height: 20%;
}
.list-item{
position: relative;
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
height: 60px;
list-style: none;
background-color: #fff;
padding-left: 10px;
font-size: large;
box-sizing: border-box;
border-bottom: 1px dashed #008cff;
transition: all .2s;
}
.list-item:hover{
background-color: rgb(235, 235, 235);
}
.item-text{
display: inline-block;
width: 80%;
}
.finish-btn, .edit-btn{
margin-right: 20px;
cursor: pointer;
width: 15%;
height: 50%;
border: 1px solid #008cff;
outline: none;
border-radius: 5px;
background-color: transparent;
color: #008cff;
font-size: 16px;
transition: all .2s;
}
.finish-btn:hover,
.edit-btn:hover,
.add-btn:hover{
background-color: #008cff;
color: #fff;
}
.container-footer{
display: flex;
justify-content: center;
align-items: center;
border-top: 1px dashed #008cff;
width: 100%;
height: 15%;
}
.add-btn{
width: 60%;
height: 55%;
border: 2px solid #008cff;
background-color: transparent;
color: #008cff;
font-size: 20px;
font-weight: 600;
font-family: '方正姚体';
border-radius: 10px;
transition: all .2s;
cursor: pointer;
}
.no-data{
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
font-weight: 600;
font-size: 26px;
color: #008cff;
}
对应样式后,结构应为:
jsx
<div className='main-container'>
<div className='main-wrap'>
<header className='note-title'>
<span>待办事项</span>
</header>
<section className='item-body'>
{
list.length === 0
? <span className='no-data'>暂无数据</span>
:
<ul className='item-container'>
{
list.map(item => {
return (
<li key={item.id} className='list-item'>
<div className='line'></div>
<span className='item-text'>{item.thing}</span>
<button onClick={()=>handleEditClick(item)} className='edit-btn'>
编辑
</button>
<button onClick={(e)=>hanleFinishClick(item.id, e)} className='finish-btn'>
点击完成
</button>
</li>
)
})
}
</ul>
}
</section>
<footer className='container-footer'>
<button onClick={handlAddClick} className='add-btn'>{'+ 添加事项'}</button>
</footer>
</div>
</div>
样式实现效果如下:
逻辑实现
使用state进行对数据的响应式操作,本项目主要涉及到对于数组的操作。
jsx
let [list, setList] = useState([]);
function hanleFinishClick(id, e){ // 完成按钮事件
// eslint-disable-next-line no-restricted-globals
let will = confirm("确认完成事件吗?");
if(will){
// 将此项从数组中移除
let newArr = list.filter(item=>item.id!==id);
setList(newArr);
}
}
function handlAddClick(){ // 添加按钮事件
// prompt函数处理,也可以使用弹出层
let thing = prompt("请输入待办事件:"); // 防止点击取消键数据变为null
if(thing){
let newList = [
...list,
{
id: nextId++,
thing
}
];
setList(newList);
}
}
function handleEditClick(item){
let newthing = prompt("请输入待办事件:", item.thing);
if(newthing){ // 防止点击取消键数据变为null
let newList = list.map((i)=>{
if(item.id === i.id){
return {
...i,
thing: newthing
}
}else{
return i;
}
});
setList(newList);
}
}
全部代码展示
jsx
import './App.css';
import { useState } from 'react';
var nextId = 0;// 全局,放里面不对
function App() {
let [list, setList] = useState([]);
function hanleFinishClick(id, e){ // 完成按钮事件
// eslint-disable-next-line no-restricted-globals
let will = confirm("确认完成事件吗?");
if(will){
// 将此项从数组中移除
let newArr = list.filter(item=>item.id!==id);
setList(newArr);
}
}
function handlAddClick(){ // 添加按钮事件
// prompt函数处理,也可以使用弹出层
let thing = prompt("请输入待办事件:"); // 防止点击取消键数据变为null
if(thing){
let newList = [
...list,
{
id: nextId++,
thing
}
];
setList(newList);
}
}
function handleEditClick(item){
let newthing = prompt("请输入待办事件:", item.thing);
if(newthing){ // 防止点击取消键数据变为null
let newList = list.map((i)=>{
if(item.id === i.id){
return {
...i,
thing: newthing
}
}else{
return i;
}
});
setList(newList);
}
}
return (
<div className='main-container'>
<div className='main-wrap'>
<header className='note-title'>
<span>待办事项</span>
</header>
<section className='item-body'>
{
list.length === 0
? <span className='no-data'>暂无数据</span>
:
<ul className='item-container'>
{
list.map(item => {
return (
<li key={item.id} className='list-item'>
<div className='line'></div>
<span className='item-text'>{item.thing}</span>
<button onClick={()=>handleEditClick(item)} className='edit-btn'>
编辑
</button>
<button onClick={(e)=>hanleFinishClick(item.id, e)} className='finish-btn'>
点击完成
</button>
</li>
)
})
}
</ul>
}
</section>
<footer className='container-footer'>
<button onClick={handlAddClick} className='add-btn'>{'+ 添加事项'}</button>
</footer>
</div>
</div>
);
}
export default App;
最终效果
初始:
添加:
成功,并点了编辑:
成功:
完成(删除):
成功:
改进方向
- 可以自己写一个小小的服务器,使得数据能够持久化存储而不是关了就没了。
- 可以将使用原生的prompt和confirm函数改为自己封装的组件或函数,以更美观更符合自己的要求。
- 可以拆分出多组件,使项目更为模块化,提高可维护性。
- 添加动画,使之不生硬,更为美观。