到了子组件,方法就没那么多了,一般子组件就是绑定事件。可以看到在子组件绑定了keyUp事件,用来确定回车键并调用父组件传来的addTodo(),将新生成的todo任务作为参数传入。
AppFooter组件
import React from "react"; export default class TodoFooter extends React.Component{ // 处理全选与全不选的状态 handlerAllState(event){ this.props.changeTodoState(null, event.target.checked, true); } // 绑定点击事件,清除已完成 handlerClick(){ this.props.clearDone(); } render(){ return ( <div className="clearfix todo-footer"> <input checked={this.props.isAllChecked} onChange={this.handlerAllState.bind(this)} type="checkbox" className="fl"/> <span className="fl">{this.props.todoDoneCount}已完成 / {this.props.todoCount}总数</span> <button onClick={this.handlerClick.bind(this)} className="fr">清除已完成</button> </div> ) } }
我们先来看看这个footer上有哪些方法。第一个就是处理todo状态的,它通过底部的checkbox的change事件触发。然后就是清空已完成的按钮的点击事件的方法handlerClick()。然后下面的数据显示,就通过props的值进行显示。
TodoMain
import React from "react"; import TodoItem from "./TodoItem.js" export default class TodoMain extends React.Component{ // 遍历显示任务,转发props render(){ return ( <ul className="todo-list"> {this.props.todos.map((todo, index) => { return <TodoItem key={index} {...todo} index={index} {...this.props}/> })} </ul> ) } }
Main组件的作用就是,将props传过来的todos遍历显示出来。所以对每一个todo的细致操作都是放在TodoItem上。
TodoItem
import React from "react"; export default class TodoItem extends React.Component{ // 处理任务是否完成状态 handlerChange(){ let isDone = !this.props.isDone; this.props.changeTodoState(this.props.index, isDone); } // 鼠标移入 handlerMouseOver(){ React.findDOMNode(this.refs.deleteBtn).style.display = "inline"; } // 鼠标移出 handlerMouseOut(){ React.findDOMNode(this.refs.deleteBtn).style.display = "none"; } // 删除当前任务 handlerDelete(){ this.props.deleteTodo(this.props.index); } render(){ let doneStyle = this.props.isDone ? {textDecoration: 'line-through'} : {textDecoration: 'none'}; return ( <li onMouseOver={this.handlerMouseOver.bind(this)} onMouseOut={this.handlerMouseOut.bind(this)} > <input type="checkbox" checked={this.props.isDone} onChange={this.handlerChange.bind(this)}/> <span style={doneStyle}>{this.props.text}</span> <button style={{'display': 'none'}} ref="deleteBtn" onClick={this.handlerDelete.bind(this)} className="fr">删除</button> </li> ) } }
在TodoItem主要处理多个交互,包括修改任务状态,删除任务。还有就是鼠标移到相应的任务上才显示删除按钮。
我们可以看到render()函数,是控制了任务的样式。标签内的style是需要接受一个对象的,所以所有的CSS属性名,都要变成驼峰形的。
总结
其实真正的回过头看React-Todos,会觉得React带给我们的组件化的思想用起来太舒服了。我们通过父组件来控制状态,并通过props传递,来保证组件内的状态一致。我们可以非常有效的维护我们的交互代码,因为我们一眼就知道,这个事件属于哪个组件管理。它的模型其实非常轻,只有View层,但是它带给我们全新的书写前端组件的方法是非常好的,我个人认为如果未来的站点交互性愈来愈多,React是很有可能代替jQuery成为必备的技能。