react——一个todolist的demo
代码如下:
function ToDoListHeader(props) { return <h1 className={props.className}>ToDoList</h1> } class CheckAll extends Component{ changeAll(event){ this.props.selectedChange('all',event.target.checked); } batchDel(){ this.props.batchDel(); } render(){ if(this.props.totalLen > 0){ return <div className="ctr"> <label htmlFor="all"> <input type="checkbox" id="all" onChange={this.changeAll.bind(this)} checked={this.props.totalLen <= this.props.selectedLen}/> {this.props.totalLen <= this.props.selectedLen ? '取消全选' :'全选'} </label> <span className="batchDel" onClick={this.batchDel.bind(this)}>批量删除</span> </div> } else { return null; } } } class InputBox extends Component{ constructor(props){ super(props); this.state = { value:'' } } handleKeyDown(event){ if(event.keyCode === 13 && this.state.value.replace(/\s/g,'').length > 0){ this.setState({ value:'' }); this.props.addToDoList(this.state.value); } } handleChange(event){ this.setState({ value:event.target.value }) } render(){ return ( <from className="inputBox"> <input type="text" className="input" value={this.state.value} onKeyDown={this.handleKeyDown.bind(this)} onChange={this.handleChange.bind(this)} placeholder="请输入..."/> <CheckAll totalLen={this.props.totalLen} selectedChange={this.props.selectedChange} selectedLen={this.props.selectedLen} batchDel={this.props.batchDel}/> </from> ) } } class ToDoItem extends Component{ delItem(){ this.props.delToDoItem(this.props.index); } changeCheck(event){ this.props.changeCheck(this.props.index,event.target.checked); } render(){ return <li> <input type="checkbox" onChange={this.changeCheck.bind(this)} checked={this.props.checked}/> <span>{this.props.label}</span> <span className="del" onClick={this.delItem.bind(this)}>X</span> </li> } } class ToDoList extends Component{ render(){ const listItem = Object.keys(this.props.listItems).map((key) => { return <ToDoItem label={this.props.listItems[key]} key={key} index={key} delToDoItem={this.props.delToDoItem} changeCheck={this.props.changeCheck} checked={this.props.selectedList[key]}/> }); return <ul className="list">{listItem}</ul> } } function ListFooter(props) { return <span className="info">一共{props.length}条</span> } class ToDoListBox extends Component{ constructor(props){ super(props); this.state = { // 列表 list:{}, // 被选中的列表项 {0:true,1:true} selectedList:{} } } // 向列表中添加条目 addToDoList(item){ this.setState((prevState) => { // 保证列表中的key不会重复 const keys = Object.keys(prevState.list).sort(); const nextKey = keys.length > 0 ? keys[keys.length-1] * 1 + 1 : 0; const list = Object.assign(prevState.list,{[nextKey]:item}); return { list:list } }) } // 从列表中删除条目 delToDoItem(index){ this.setState((prevSate) => { delete prevSate.list[index]; return { list:prevSate.list } }); this.selectedChange(index,false) } // 批量删除 batchDel(){ Object.keys(this.state.selectedList).forEach((key) => { this.delToDoItem(key); this.selectedChange(key,false); }) } selectedChange(key,checked){ // 取消全选 if(key === 'all' && !checked){ this.setState({ selectedList:{} }); return; } // 全选 if(key === 'all' && checked){ const list = this.state.list; let selectObj = {}; Object.keys(list).forEach((key) => { selectObj[key] = true }); this.setState({ selectedList:selectObj }); return; } // 选择或取消选择某一个 this.setState((prevState) => { if(checked && !prevState.selectedList[key]){ return { selectedList:Object.assign(prevState.selectedList,{[key]:true}) } } if(!checked && prevState.selectedList[key]){ delete prevState.selectedList[key]; return { selectedList:prevState.selectedList } } }) } render(){ const selectedLen = Object.keys(this.state.selectedList).length; const listLen = Object.keys(this.state.list).length return ( <div> <InputBox addToDoList={this.addToDoList.bind(this)} totalLen={listLen} selectedLen={selectedLen} selectedChange={this.selectedChange.bind(this)} batchDel={this.batchDel.bind(this)}/> <ToDoList listItems={this.state.list} delToDoItem={this.delToDoItem.bind(this)} changeCheck={this.selectedChange.bind(this)} selectedList={this.state.selectedList}/> <ListFooter length={listLen}/> </div> ) } } class App extends Component { render() { return ( <div className="warp"> <logo/> <ToDoListHeader className="header"/> <ToDoListBox/> </div> ); } }