本小节,我们要实现点击复选框,修改任务项的实时状态,但是Item
组件和App
组件是祖孙关系,不是父子关系,我们还能使用props
进行通信吗?答案是可以的。
在App组件定义一个更新的函数并传递给Item组件
- 1、定义一个更新状态数据的函数
// 更新状态数据 updateTodo = () => { const { todos } = this.state console.log(todos) }
- 2、先传递给List组件
render() { const {todos,updateTodo} = this.props return ( <ul className="todo-main"> { todos.map(todo=>{ return <Item key={todo.id} {...todo} updateTodo={updateTodo}/> }) } </ul> ) }
- 3、在Item组件定义一个onChange事件的回调
import React, { Component } from 'react' import "./index.css" export default class Item extends Component { // 初始化状态数据 state = {mouseIn:false} // 鼠标移入移出回调函数 mouseHandle = (flag) => { this.setState({mouseIn:flag}) } // 更新任务项状态 checkHandle = (id,event) => { this.props.updateTodo(id,event.target.checked) } render() { const {id,name,done} = this.props const {mouseIn} = this.state return ( <li onMouseEnter={()=>this.mouseHandle(true)} onMouseLeave={()=>this.mouseHandle(false)} style={{backgroundColor: mouseIn?'gainsboro':''}}> <label> <input type="checkbox" defaultChecked={done} onChange={event=>this.checkHandle(id,event)}/> <span>{name}</span> </label> <button className="btn btn-danger" style={{display:mouseIn?"block":"none"}}>删除</button> </li> ) } }
我们给复选框绑定了一个onChange的回调函数checkHandle(id,event)
并把id
和event
作为参数。当我们点击复选框的时候,我们将参数传递给updateTodo
函数,让其修改App
组件的状态数据。
- 4、改造updateTodo函数
// 更新状态数据 updateTodo = (id,done) => { const { todos } = this.state const newTodos = todos.map(todoObj=>{ if (id === todoObj.id) return {...todoObj,done} return todoObj }) this.setState({todos:newTodos}) }
这里我们判断如果id
值与列表里面的id
值匹配,我们就更新done
值的状态,否则不做改变,原样返回。
- 5、具体效果
我们可以从图中看到,当我们点击列表的复选框,修改了任务项的状态时,react
开发者工具里面的state
值也会实时变化,至此,说明我们已经完成数据的实时更新。
小总结
- 获取复选框的状态值使用:
event.target.checked
- 祖孙组件之间的通信也可以使用props进行传递。