整个程序使用到的知识点:自定义组件、父子组件间通讯、多级组件间通讯、hook、自定义hook等
程序分为四个js文件
TodoList.jsx 最高级组件
Input.jsx 输入区域组件
List.jsx 列表组件
Item.jsx 列表项组件
效果图展示:
代码如下:
TodoList.jsx文件
注意点:需要调用ArrDisposeFn(()=>[...arr])回调方法,实现逻辑层与视图层同步改变,如果不调用会出现逻辑层数据改变,视图层数据不更新的bug
ArrDisposeFn方法是我们创建hook数据时一并创建的方法
import React, { useState } from 'react'
import './TodoList.css'
// 组件
import List from '../List/List'
import Input from '../Input/Input'
// 多级传递
import context from '../notext/notext'
const {Provider}=context
let id=4;
// 自定义hook
const ArrOperateFn=()=>{
const[arr,ArrDisposeFn]=useState([
{id:0,title:'起床',checked:false},
{id:1,title:'吃饭',checked:false},
{id:2,title:'睡觉',checked:false},
{id:3,title:'摆烂',checked:true}
])
// 添加方法
const AddOperateFn=(val)=>{
ArrDisposeFn([...arr,{id:id++,title:val,checked:false}])
}
// 删除方法
const DelOperateFn=(id)=>{
const index=arr.findIndex(item=>item.id===id)
arr.splice(index,1)
ArrDisposeFn([...arr])
}
// 选择状态
const ChangeStatus=(id)=>{
const index=arr.findIndex(item=>item.id===id)
arr[index].checked=!arr[index].checked
ArrDisposeFn([...arr])
}
return[arr,AddOperateFn,DelOperateFn,ChangeStatus]
}
export default function TodoList() {
const[arr,AddOperateFn,DelOperateFn,ChangeStatus]=ArrOperateFn()
return (
<div className='TodoListContent'>
<div className='TodoListTitle'>TodoList-DEMO</div>
<Input addFn={AddOperateFn}/>
<Provider value={
{DelOperateFn:DelOperateFn,ChangeStatus:ChangeStatus}}>
<List title="正在进行" arr={arr.filter(item=>!item.checked)} />
<List title="已经完成" arr={arr.filter(item=>item.checked)} />
</Provider>
</div>
)
}
TodoList.css样式文件
*{padding: 0;margin: 0;}
.TodoListContent{
width: 600px;
box-sizing: border-box;
padding: 0 20px;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%,-50%);
border-radius: 7px;
border: 1px solid #000;
}
.TodoListTitle{
font-size: 35px;
font-weight: 700;
padding: 10px;
border-bottom: 2px dashed #000;
}
Input.jsx文件
import React, { useState } from 'react'
import './Input.css'
export default function Input(props) {
const [value,onChangeFn]=useState('')
return (
<div className='InputContent'>
<input type="text" value={value} onChange={(e)=>onChangeFn(e.target.value)} />
<button onClick={()=>{
if(!value){
window.alert('内容不能为空')
return
}
props.addFn(value)
onChangeFn('')
}}>添加</button>
</div>
)
}
Input.css样式文件
.InputContent{
width: 100%;
padding: 30px 0;
display: flex;
justify-content: center;
border-bottom: 1px solid #efefef;
}
.InputContent input{
width: 300px;
height: 30px;
padding-left: 20px;
box-sizing: border-box;
border: 1px solid #000;
border-radius: 5px;
}
button{
width: 90px;
height: 34px;
margin-left: 40px;
border-radius: 5px;
border: 1px solid #ccc;
box-shadow: 2px 2px 2px #000;
vertical-align: middle;
}
List.jsx文件
import React from 'react'
import Item from '../Item/Item'
import './List.css'
export default function List(props) {
return (
<div className='ListContent'>
<div className='ListTitle'>{props.title}</div>
<ul>
{props.arr.map(item=><Item key={item.id} item={item} />)}
</ul>
</div>
)
}
List.css样式文件
.ListTitle{
font-size: 20px;
font-weight: 600;
padding-top: 20px;
}
Item.jsx文件
import React, {useContext } from 'react'
import context from '../notext/notext';
import './Item.css'
export default function Item(props) {
const superlative=useContext(context)
return (
<li>
<label className='content'>
<input type="checkbox" checked={props.item.checked} onChange={()=>{
superlative.ChangeStatus(props.item.id)
}} />
{props.item.title}
</label>
<div className='delBtn' onClick={()=>{
if(window.confirm(`确认删除${props.item.title}吗?`)){
superlative.DelOperateFn(props.item.id)
}
}}>删除</div>
</li>
)
}
Item.css样式文件
li{
display: flex;
justify-content: space-between;
list-style: none;
border-bottom: 1px solid #efefef;
}
.content{
padding: 15px 10px;
width: 100%;
}
.content input{
vertical-align: middle;
margin-right: 12px;
}
.delBtn{
width: 80px;
padding: 15px 0;
cursor: pointer;
text-align: center;
}
全篇重点掌握react函数组件的使用、react的hook的定义与使用、函数式组件的父子间通讯、函数式组件的多级组件间通讯等,相应的知识点笔记后期会更新上,尽请期待.....