React入门实践之TodoList: 添加事件和搜索框

前端之家收集整理的这篇文章主要介绍了React入门实践之TodoList: 添加事件和搜索框前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

在上篇文章中,我们使用React实现了一个TodoList,可以显示基本的待办事项的列表,今天我们继续添加一些功能,比如选中一个TodoItem的checkBox进而可以改变它的完成状态,添加一个搜索框,在搜索框中输入关键字可以对多条数据进行过滤。
我们还是在原来的基础上做改动,下面是最新的TodoList模块:

  1. var TodoList = React.createClass({
  2. getInitialState: function() {
  3. return {
  4. data: []
  5. };
  6. },componentDidMount: function() {
  7. var mockData = [
  8. {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"}
  9. ];
  10.  
  11. this.setState({
  12. data: mockData
  13. });
  14. },render: function() {
  15. var todoItems = this.state.data.map(function(todo) {
  16. return (
  17. //passing the whole todo object as a property
  18. <TodoItem key={todo.id} todo={todo}/>
  19. );
  20. });
  21.  
  22. return (
  23. <div className="todoList">{todoItems}</div>
  24. );
  25. }
  26. });

在上面的代码中,我们改进了TodoItem属性的传递方式,直接把一个todo数据对象作为属性提供给TodoItem,这样更利于开发过程中的数据处理。接下来,我们也要对TodoItem模块进行改进,代码如下:

  1. var TodoItem = React.createClass({
  2. //will be called after clicking the checkBox
  3. handleClick: function(event) {
  4. var todoData = this.props.todo;
  5.  
  6. todoData.hasDone = !todoData.hasDone;
  7.  
  8. //re-render the view
  9. this.setState({
  10. hasDone: todoData.hasDone
  11. });
  12.  
  13. //Ajax handling maybe
  14. //updateTodo(this.props.todo);
  15. },getInitialState: function() {
  16. return {
  17. hasDone: false
  18. };
  19. },componentDidMount: function() {
  20. this.setState({
  21. hasDone: this.props.todo.hasDone
  22. });
  23. },render: function() {
  24. var classList = ['todoItem'];
  25. this.state.hasDone && classList.push('hasDone'); //add a 'hasDone' class after checkBox is checked
  26. var classNames = classList.join(' ');
  27.  
  28. return (
  29. //adding 'onClick' property on checkBox to bind a click handler
  30. <div className={classNames}>
  31. <input type="checkBox" onClick={this.handleClick} checked={this.props.todo.hasDone}/>
  32. <div className="name">{this.props.todo.name}</div>
  33. <div className="time">{this.props.todo.time}</div>
  34. </div>
  35. );
  36. }
  37. });

这一部分改动的较多,我们仔细来分析每个部分的功能
首先是getInitialState部分,我们添加了初始状态,hasDone表示一个待办事项是否已经完成,初始值为false,然后在componentDidMount函数中,我们根据上层传递进来的数据重新设置状态,这个状态最终会在render方法中起作用。
render方法中我们会首先判断这个Todo是否已经完成,如果已完成,就为其添加一个hasDone的className,最终会在页面显示不同的样式。然后我们为checkBox声明了checked属性,它会根据数据中的hasDone来显示选中状态,这就意味着如果一个Todo是已完成的,页面初始化时这个checkBox是被选中的。
最后,我们为checkBox绑定一个点击事件,当它被点击时,handleClick函数就会被触发,在这个函数中,我们会获取最新的hasDone值,然后重置状态更新视图,实际开发中我们还需要做一些Ajax操作请求服务器更改数据库中的值。
最后,我们添加一个hasDone对应的样式:

  1. .todoItem.hasDone > div { text-decoration: line-through; }

现在我们来看一下最终的页面效果,如图所示,当我们点击第一个TodoItem后是这个样子的:

我们已经成功地添加了点击事件,下面我们还需要为这个TodoList添加一个过滤的功能,先创建一个SearchBox模块:

  1. var SearchBox = React.createClass({
  2. render: function() {
  3. return (
  4. <div className="searchBox">
  5. <input type="text" placeholder="type in keywords to search"/>
  6. </div>
  7. );
  8. }
  9. });

然后声明对应的CSS样式:

  1. .searchBox { width: 400px; height: 100%; margin: 0 auto; }
  2. .searchBox input { width: 100%; height: 30px; border: none; padding: 5px 15px; border-radius: 2px; font-size: 14px; }

最后还需在TodoList模块的render方法中把SearchBox添加进去:

  1. render: function() {
  2. var todoItems = this.state.data.map(function(todo) {
  3. return (
  4. <TodoItem key={todo.id} todo={todo}/>
  5. );
  6. });
  7.  
  8. return (
  9. <div className="todoList">
  10. <SearchBox/>
  11. {todoItems}
  12. </div>
  13. );
  14. }

现在可以预览一下页面效果

下一步就要为SearchBox添加事件处理了,我们需要好好思考一下如何将文本框中的输入与TodoItems关联起来。首先,要想对数据集进行过滤,TodoList模块中必须定义一个表示搜索关键字的变量,进而对数据集进行操作,然后,这里的关键字是SearchBox提供的,所以SearchBox模块中的文本框数据变化必须通知TodoList模块,做下一步的处理。
现在我们来修改一下TodoList的代码

  1. var TodoList = React.createClass({
  2. handleSearchTextUpdate: function(searchText) {
  3. this.state.searchText = searchText;
  4. this.setState(this.state);
  5. },getInitialState: function() {
  6. return {
  7. data: [],searchText: '' //adding a searchText,it will be used in render method
  8. };
  9. },time: "11:00"}
  10. ];
  11.  
  12. this.state.data = mockData;
  13.  
  14. this.setState(this.state);
  15. },render: function() {
  16. var state = this.state;
  17.  
  18. //filter the data first and then call map function
  19. var todoItems = state.data.filter(function(todo) {
  20. return todo.name.toLowerCase().indexOf(state.searchText.toLowerCase()) > -1;
  21. }).map(function(todo) {
  22. return (
  23. <TodoItem key={todo.id} todo={todo}/>
  24. );
  25. });
  26.  
  27. return (
  28. //adding a 'onSearchTextUpdate' callback,it will be called when text changes in search input
  29. <div className="todoList">
  30. <SearchBox onSearchTextUpdate={this.handleSearchTextUpdate}/>
  31. {todoItems}
  32. </div>
  33. );
  34. }
  35. });

可以看到,在getInitialState方法中,我们添加了一个searchText的值,用于表示过滤的关键字,然后在render方法中,我们会使用filter函数对数据集进行过滤,searchText也就是在这个时候发挥它的作用的。接着在SearchBox声明时我们添加onSearchTextUpdate属性作为搜索文本变化后的回调函数,它实际上会执行handleSearchTextUpdate函数,进而设置新的searchText,然后重置state刷新视图。
那么在SearchBox模块,我们需要做的就是监听文本框中输入的变化,然后调用上面提到的回调函数,把最新的输入传递上去,来看一下修改过的代码

  1. var SearchBox = React.createClass({
  2. handleChange: function(event) {
  3. var newInput = event.target.value;
  4.  
  5. //call the onSearchTextUpdate in props
  6. this.props.onSearchTextUpdate(newInput);
  7. },render: function() {
  8. return (
  9. //adding a 'onChange' to monitor the value changes
  10. <div className="searchBox">
  11. <input type="text" onChange={this.handleChange} placeholder="type in keywords to search"/>
  12. </div>
  13. );
  14. }
  15. });

过滤功能只是在TodoList和SearchBox之间的交互,TodoItem是不需要任何改动的,所以只需弄清楚SearchBox和TodoList之间的交互,就可以很快实现一个过滤功能,下面是我们最终的页面效果
如果你是一个Angular的爱好者,可能觉得React使用起来会比较绕,那么你需要仔细揣摩整个实现过程,或许你还会稍微有点喜欢它呢~

猜你在找的React相关文章