代码如下:
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>
);
}
}