React入门实践之TodoList: 添加事件和搜索框
2016-05-23 12:53
627 查看
在上篇文章中,我们使用React实现了一个TodoList,可以显示基本的待办事项的列表,今天我们继续添加一些功能,比如选中一个TodoItem的checkbox进而可以改变它的完成状态,添加一个搜索框,在搜索框中输入关键字可以对多条数据进行过滤。
我们还是在原来的基础上做改动,下面是最新的TodoList模块:
在上面的代码中,我们改进了TodoItem属性的传递方式,直接把一个todo数据对象作为属性提供给TodoItem,这样更利于开发过程中的数据处理。接下来,我们也要对TodoItem模块进行改进,代码如下:
这一部分改动的较多,我们仔细来分析每个部分的功能。
首先是
在
最后,我们为checkbox绑定一个点击事件,当它被点击时,handleClick函数就会被触发,在这个函数中,我们会获取最新的hasDone值,然后重置状态更新视图,实际开发中我们还需要做一些Ajax操作请求服务器更改数据库中的值。
最后,我们添加一个hasDone对应的样式:
现在我们来看一下最终的页面效果,如图所示,当我们点击第一个TodoItem后是这个样子的:
我们已经成功地添加了点击事件,下面我们还需要为这个TodoList添加一个过滤的功能,先创建一个SearchBox模块:
然后声明对应的CSS样式:
最后还需在TodoList模块的render方法中把SearchBox添加进去:
现在可以预览一下页面效果:
下一步就要为SearchBox添加事件处理了,我们需要好好思考一下如何将文本框中的输入与TodoItems关联起来。首先,要想对数据集进行过滤,TodoList模块中必须定义一个表示搜索关键字的变量,进而对数据集进行操作,然后,这里的关键字是SearchBox提供的,所以SearchBox模块中的文本框数据变化必须通知TodoList模块,做下一步的处理。
现在我们来修改一下TodoList的代码:
可以看到,在
那么在SearchBox模块,我们需要做的就是监听文本框中输入的变化,然后调用上面提到的回调函数,把最新的输入传递上去,来看一下修改过的代码:
过滤功能只是在TodoList和SearchBox之间的交互,TodoItem是不需要任何改动的,所以只需弄清楚SearchBox和TodoList之间的交互,就可以很快实现一个过滤功能,下面是我们最终的页面效果:
如果你是一个Angular的爱好者,可能觉得React使用起来会比较绕,那么你需要仔细揣摩整个实现过程,或许你还会稍微有点喜欢它呢~
我们还是在原来的基础上做改动,下面是最新的TodoList模块:
var TodoList = React.createClass({ getInitialState: function() { return { data: [] }; }, componentDidMount: function() { var mockData = [ {id: 1, name: "report the updates to Boss", time: "9:30"}, {id: 2, name: "Stand-up meeting", time: "10:00"}, {id: 3, name: "Draw up a plan for next step", time: "11:00"} ]; this.setState({ data: mockData }); }, render: function() { var todoItems = this.state.data.map(function(todo) { return ( //passing the whole todo object as a property <TodoItem key={todo.id} todo={todo}/> ); }); return ( <div className="todoList">{todoItems}</div> ); } });
在上面的代码中,我们改进了TodoItem属性的传递方式,直接把一个todo数据对象作为属性提供给TodoItem,这样更利于开发过程中的数据处理。接下来,我们也要对TodoItem模块进行改进,代码如下:
var TodoItem = React.createClass({ //will be called after clicking the checkbox handleClick: function(event) { var todoData = this.props.todo; todoData.hasDone = !todoData.hasDone; //re-render the view this.setState({ hasDone: todoData.hasDone }); //Ajax handling maybe //updateTodo(this.props.todo); }, getInitialState: function() { return { hasDone: false }; }, componentDidMount: function() { this.setState({ hasDone: this.props.todo.hasDone }); }, render: function() { var classList = ['todoItem']; this.state.hasDone && classList.push('hasDone'); //add a 'hasDone' class after checkbox is checked var classNames = classList.join(' '); return ( //adding 'onClick' property on checkbox to bind a click handler <div className={classNames}> <input type="checkbox" onClick={this.handleClick} checked={this.props.todo.hasDone}/> <div className="name">{this.props.todo.name}</div> <div className="time">{this.props.todo.time}</div> </div> ); } });
这一部分改动的较多,我们仔细来分析每个部分的功能。
首先是
getInitialState部分,我们添加了初始状态,
hasDone表示一个待办事项是否已经完成,初始值为
false,然后在
componentDidMount函数中,我们根据上层传递进来的数据重新设置状态,这个状态最终会在render方法中起作用。
在
render方法中我们会首先判断这个Todo是否已经完成,如果已完成,就为其添加一个hasDone的className,最终会在页面中显示不同的样式。然后我们为checkbox声明了checked属性,它会根据数据中的hasDone来显示选中状态,这就意味着如果一个Todo是已完成的,页面初始化时这个checkbox是被选中的。
最后,我们为checkbox绑定一个点击事件,当它被点击时,handleClick函数就会被触发,在这个函数中,我们会获取最新的hasDone值,然后重置状态更新视图,实际开发中我们还需要做一些Ajax操作请求服务器更改数据库中的值。
最后,我们添加一个hasDone对应的样式:
.todoItem.hasDone > div { text-decoration: line-through; }
现在我们来看一下最终的页面效果,如图所示,当我们点击第一个TodoItem后是这个样子的:
我们已经成功地添加了点击事件,下面我们还需要为这个TodoList添加一个过滤的功能,先创建一个SearchBox模块:
var SearchBox = React.createClass({ render: function() { return ( <div className="searchBox"> <input type="text" placeholder="type in keywords to search"/> </div> ); } });
然后声明对应的CSS样式:
.searchBox { width: 400px; height: 100%; margin: 0 auto; } .searchBox input { width: 100%; height: 30px; border: none; padding: 5px 15px; border-radius: 2px; font-size: 14px; }
最后还需在TodoList模块的render方法中把SearchBox添加进去:
render: function() { var todoItems = this.state.data.map(function(todo) { return ( <TodoItem key={todo.id} todo={todo}/> ); }); return ( <div className="todoList"> <SearchBox/> {todoItems} </div> ); }
现在可以预览一下页面效果:
下一步就要为SearchBox添加事件处理了,我们需要好好思考一下如何将文本框中的输入与TodoItems关联起来。首先,要想对数据集进行过滤,TodoList模块中必须定义一个表示搜索关键字的变量,进而对数据集进行操作,然后,这里的关键字是SearchBox提供的,所以SearchBox模块中的文本框数据变化必须通知TodoList模块,做下一步的处理。
现在我们来修改一下TodoList的代码:
var TodoList = React.createClass({ handleSearchTextUpdate: function(searchText) { this.state.searchText = searchText; this.setState(this.state); }, getInitialState: function() { return { data: [], searchText: '' //adding a searchText, it will be used in render method }; }, componentDidMount: function() { var mockData = [ {id: 1, name: "report the updates to Boss", time: "9:30"}, {id: 2, name: "Stand-up meeting", time: "10:00"}, {id: 3, name: "Draw up a plan for next step", time: "11:00"} ]; this.state.data = mockData; this.setState(this.state); }, render: function() { var state = this.state; //filter the data first and then call map function var todoItems = state.data.filter(function(todo) { return todo.name.toLowerCase().indexOf(state.searchText.toLowerCase()) > -1; }).map(function(todo) { return ( <TodoItem key={todo.id} todo={todo}/> ); }); return ( //adding a 'onSearchTextUpdate' callback, it will be called when text changes in search input <div className="todoList"> <SearchBox onSearchTextUpdate={this.handleSearchTextUpdate}/> {todoItems} </div> ); } });
可以看到,在
getInitialState方法中,我们添加了一个
searchText的值,用于表示过滤的关键字,然后在render方法中,我们会使用filter函数对数据集进行过滤,searchText也就是在这个时候发挥它的作用的。接着在SearchBox声明时我们添加了
onSearchTextUpdate属性作为搜索文本变化后的回调函数,它实际上会执行handleSearchTextUpdate函数,进而设置新的searchText,然后重置state刷新视图。
那么在SearchBox模块,我们需要做的就是监听文本框中输入的变化,然后调用上面提到的回调函数,把最新的输入传递上去,来看一下修改过的代码:
var SearchBox = React.createClass({ handleChange: function(event) { var newInput = event.target.value; //call the onSearchTextUpdate in props this.props.onSearchTextUpdate(newInput); }, render: function() { return ( //adding a 'onChange' to monitor the value changes <div className="searchBox"> <input type="text" onChange={this.handleChange} placeholder="type in keywords to search"/> </div> ); } });
过滤功能只是在TodoList和SearchBox之间的交互,TodoItem是不需要任何改动的,所以只需弄清楚SearchBox和TodoList之间的交互,就可以很快实现一个过滤功能,下面是我们最终的页面效果:
如果你是一个Angular的爱好者,可能觉得React使用起来会比较绕,那么你需要仔细揣摩整个实现过程,或许你还会稍微有点喜欢它呢~
相关文章推荐
- ReactiveCocoa之RAC常用宏(十)
- ReactiveCocoa之RAC合并(九)
- ReactiveCocoa之RAC过滤(八)
- ReactiveCocoa之RAC映射(七)
- ReactiveCocoa之RACMulticastConnection使用(六)
- ReactiveCocoa之RACCommand使用(五)
- ReactiveCocoa之RACSubject用法(四)
- ReactiveCocoa之RACSignal核心类的使用(三)
- ReactiveCocoa之常见用法(二)
- React-native debug errors
- 离线安装Chrome扩展程序
- ReactiveCocoa之简介(一)
- 响应式编程框架ReactiveCocoa学习——框架概览
- React Native学习笔记(二)JSX 语法学习
- Reacting to rumors
- React Native 安装开发环境及如何编写Hello World程序
- 响应式编程框架ReactiveCocoa学习——基本操作符
- ReactiveCocoa之进阶篇
- ReactiveCocoa之基础
- ZOJ2314Reactor Cooling(无源汇上下界可行流)