React入門實踐之TodoList: 添加事件和搜尋方塊

來源:互聯網
上載者:User

在上篇文章中,我們使用React實現了一個TodoList,可以顯示基本的待辦事項的列表,今天我們繼續添加一些功能,比如選中一個TodoItem的checkbox進而可以改變它的完成狀態,添加一個搜尋方塊,在搜尋方塊中輸入關鍵字可以對多條資料進行過濾。
我們還是在原來的基礎上做改動,下面是最新的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使用起來會比較繞,那麼你需要仔細揣摩整個實現過程,或許你還會稍微有點喜歡它呢~

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.