本小节,我们来实现最后的Footer组件的功能,它的功能主要有:
- 记录已完成和全部的任务列表数量
- 点击【复选框】可以实现全选和全不选
- 点击【删除已完成】按钮,可以将选中的任务项删除掉
实现已完成和全部的任务列表数量
步骤1:在App
组件将todos
的状态通过props
传递给Footer
组件
<Footer todos={todos} />
步骤2:Footer组件接收数据并计算长度
export default class Footer extends Component { render() { const {todos} = this.props // 计算列表的长度 const len = todos.length // 计算已完成的列表长度 const doneLen = todos.reduce((pre,cur)=>{ return pre + (cur.done ? 1:0) },0) return ( <div className="todo-footer"> <label> <input type="checkbox"/> </label> <span> <span>已完成{doneLen}</span> / 全部{len} </span> <button className="btn btn-danger">清除已完成任务</button> </div> ) } }
步骤3:查看效果
可以看到我们选中和取消选中时,已完成和全部的长度变化,和我们期望的一样。
实现【复选框】可以实现全选和全不选
- 1、在
App
组件里面编写函数逻辑,并传递函数给Footer
组件
// 实现全选和全不选 selectAllData = (done) => { console.log(done) const {todos} = this.state const newTodos = todos.map(todo=>{ return {...todo,done} }) this.setState({todos:newTodos}) }
<Footer todos={todos} selectAllData={this.selectAllData} />
- 2、给props添加限制
// 对props做类型和必要性的限制 static propTypes = { selectAllData:PropTypes.func.isRequired, }
- 3、给
Footer
组件的复选框添加属性和事件回调
// 全选和全不选的事件回调 checkAllHandle = (event) => { this.props.selectAllData(event.target.checked) }
<input type="checkbox" checked={len === doneLen && len!==0 ? true:false} onChange={this.checkAllHandle} />
- 4、查看效果
为什么没有效果呢?难道是我代码写的有问题?检查了一下,代码确实有问题,但是不是这里的问题,而是在Item组件里面的复选框的defaultChecked
属性的问题。我们改为checked
属性就好。
<input type="checkbox" defaultChecked={done} onChange={event=>this.checkHandle(id,event)}/>
===>
<input type="checkbox" checked={done} onChange={event=>this.checkHandle(id,event)}/>
修改好后,我们再看效果:
我们看到已经可以全选和全不选了。
实现【删除已完成】按钮,可以将选中的任务项删除掉
- 1、在
App
组件里面编写好删除已完成的列表数据的函数代码逻辑,并传递给Footer
组件
// 删除已完成的任务项 deleteDoneData = () => { const {todos} = this.state const newTodos = todos.filter(todo=>{ return !todo.done }) this.setState({todos:newTodos}) }
<Footer todos={todos} selectAllData={this.selectAllData} deleteDoneData={this.deleteDoneData} />
- 2、给props添加限制
// 对props做类型和必要性的限制 static propTypes = { selectAllData:PropTypes.func.isRequired, deleteDoneData:PropTypes.func.isRequired }
- 3、给【删除已完成】按钮添加点击事件回调函数
// 删除已完成的任务项 deleteDoneHandle = () => { this.props.deleteDoneData() }
<button onClick={this.deleteDoneHandle} className="btn btn-danger">清除已完成任务</button>
- 4、查看效果
由图可知该功能已完成。
查看完整功能
小总结
- 熟悉数组函数
reduce/map/filter...
- 了解
react
中的defaultChecked
与checked
属性的区别
defaultChecked和checked是React中用于处理表单元素的两个属性。它们之间的区别在于:
defaultChecked是用于设置表单元素的默认选中状态的属性。当组件首次渲染时,如果没有传递checked属性,则会使用defaultChecked属性来设置表单元素的选中状态。如果传递了checked属性,则defaultChecked属性将被忽略。
checked是用于设置表单元素的选中状态的属性。当组件渲染时,如果传递了checked属性,则会使用该属性来设置表单元素的选中状态。如果没有传递checked属性,则会使用defaultChecked属性来设置表单元素的选中状态。
简单的说: defaultChecked属性 用于设置复选框的 默认选中状态,而 checked属性 用于设置复选框的 当前选中状态。当复选框的选中状态发生变化时,我们使用onChange事件处理程序来更新组件的状态 。checked属性要配合onChange事件处理一起使用,不然react会报错。