react使用hook实现TodoList

整个程序使用到的知识点:自定义组件、父子组件间通讯、多级组件间通讯、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的定义与使用、函数式组件的父子间通讯、函数式组件的多级组件间通讯等,相应的知识点笔记后期会更新上,尽请期待.....

猜你喜欢

转载自blog.csdn.net/Binglianxiaojiao/article/details/128449485