实现TodoList(简易版)
今天用react实现一个todolist!
首先将整个功能拆分为四个组件,Header、List、Item、Footer。
它的目录结构如下:
APP.tsx
整体功能都放在这里,在这里进行list的状态管理。
注意,传过去的变量需要用useState进行状态管理,否则会出现检测不到变量变化的bug的!
注意更新list时可以使用map来更新状态
const updateItem = (id: string, checked: boolean) => {
let newList = list.map(item => {
if (item.id === id) return { ...item, checked };
else return item;
});
setList(newList);
}
Header.tsx
输入框,用于增添Item。
通过接收App.tsx中传过来的addItem来进行对list的添加。
export default function Header(props: Props) {
const { addItem } = props;
const [val,setVal] = useState('');
function handleKeyUp(e: any) {
if (e.key == 'Enter') {
addItem(val);
}
}
function handleChange(e: any) {
console.log(e.target.value);
setVal(e.target.value);
}
return (
<>
<input type="text" placeholder='请输入待办事项,回车确认' onKeyUp={handleKeyUp} onChange={debounce(handleChange,0)} />
</>
)
}
List.tsx
存放Item
<div className='container'>
{
list.map((item:TItem) => {
return <Item key={item.id} value={item.value}/>
})
}
</div>
这里写了发现没渲染上去,检查了半天发现是没在map里写return😭 (记得key也要写~)
简化了一下不写return的方式
list.map((item:TItem) => <Item key={item.id} value={item.value}/>)
Item.tsx
用于展示单个的item内容。
注意这里的handleCheck形式。
const handleCheck = (id: string) => {
return (e:any) => {
updateItem(id,e.target.checked);
}
}
<input type="checkbox" checked={checked} onChange={handleCheck(id)} name="" id="" />
Footer.tsx
显示底部已完成/全部的数量,可以全选或全不选。
已完成的数量的变化,可以在App.jsx中通过useEffect来监测
useEffect(() => {
let n = 0;
list.forEach(item => {
if (item.checked) ++n;
})
setNum(n);
}, [list])
也可以直接在Footer.jsx来计算已完成数量
//已完成的个数
const num = list.reduce((pre,todo)=> pre + (todo.done ? 1 : 0),0);
全选check的判断可以用下面这种方式
<input type="checkbox" checked={num === sum && sum !== 0} onChange={handleChange} name="" id="" />
整体样式: