你已經學會在 React 中如何顯示資料了, 現在我們來看看如何讓使用者界面產生互動性.
A Simple Example
1 | var LikeButton = React.createClass({ |
Event Handing and Synthetic Events
在 React 中, 你只要簡單地用駝峰式大小寫 (camelCased) 的事件命名方式帶入你的事件處理函式 (event handler). React 用一種合成事件系統 (synthetic event system) 確保事件處理在 IE8 以上的瀏覽器都能夠正常運作. 這個系統會去處理事件上升泡泡(bubble)階段和事件下降捕捉(capture)階段. 有關於 Javascript Event 的處理機制可以參考這篇文章. 所有在 React 傳遞的事件會被封裝成一個 SyntheticEvent 的事件物件, 並保證無論你使用什麼瀏覽器都與 W3C spec 的規格相容.
如果你想要使用 React 運行在像是手機和平板等支援觸碰感應的裝置(touch device), 你只要簡單地呼叫React.initializeTouchEvents(true)就能開啟觸碰事件機制.
Under the Hood: Autobinding and Event Delegation
進一步地說, React 作了一些努力讓你的程式碼保持乾淨以及容易閱讀.
Autobinding
當一般我們在建立 callback 函式時, 都會需要特別綁定 (bind) 這個方法 (method) 到某個實例 (instance), 這樣當呼叫
this時才能如預期地執行正確. 在 React 中, 每一個方法都會被自動綁定到當前的組件實例 (component instance). React 會快取這些被綁定的方法使執行更加快速以及節約記憶體的開銷. 當然, 也讓我們少打了一些字!Event delegation
事件委派, React 並不會實際地將事件處理函式 (event handlers) 連接到 DOM 結點. 當 React 啟動時, 它會用一個 event listener 開始監聽最上層的所有事件. 當組件掛載 (mount) 或是卸載 (unmount) 時, 事件處理函式會被加入或移除一個內部的對照表(mapping). 當事件發生時, React 會依據對照表轉發事件. 當沒有任何的 event handler 在對照表時, React 的 event handlers 將不會有任何處理. 想要了解為什麼這樣的執行效能最好, 可以看看 David Walsh 的這篇文章
Components are Just State Machines
React 將使用者界面(UIs)視為一種簡單的有限狀態機(State Machines). 由於界面在不同狀態下會有不同的顯示面貌, 用這種思維可以讓你的界面處理一致化.
在 React 中, 你只要簡單地變更組件的狀態(state), 接著就會基於這個新的狀態產生新界面的外觀. React 會以最節約的方式幫你更新 DOM 的結構.
How State Works
一個最普遍的作法就是呼叫 setState(data, [callback]) 來通知 React 資料的改變, 這個方法會合併 data 到 this.state, 然後重新 render 組件. 當組件更新完, callback 會被執行呼叫. 大部分你將不需要帶入 callback 參數, 因為 React 會自已幫你把界面更新到最後狀態的版本.
What Components Should Have State?
大部分你的組件應只需簡單帶入 props 資料然後 render 它. 但有時候你會需要回應一個使用者的操作, 一個伺服器的請求或是時間流逝的過程. 像這些情況你會需要用到 state.
盡可能地使你的組件維持在無狀態的運作
這樣你比較可以把有關於狀態的邏輯處理集中在某一個程式片段中, 簡少無謂的程式碼, 使你的程式更容易被閱讀.
一個常見的作法就是建立數個無狀態的組件, 它們只負責顯示資料, 然後用一個最上層擁有狀態的組件將狀態經由 props 傳遞到子元素. 這個有狀態的組件將承攔全部的互動邏輯, 而那些無狀態的組件只需要關心怎麼呈現資料就好.
What should Go in State
狀態應存放組件的 event handlers 會需要改變且通知界面改變的資料
實際應用中, 狀態的資料趨向於愈小愈好並且 JSON 序列化. 當建構一個有狀態的組件時, 思考如何盡可能地最精簡地表達它的狀態資料內容, 然後只將這些資料存放在 this.state. 然後在 render() 中簡單地與其它狀態的資料計算結果. 你將會發現用這樣的方式所寫出來的程式最不容易出錯, 而加入過多的資料或是將計算結果放到狀態中, 代表著你將會比單純依賴 React 的計算機制花更多的心力去維持資料的同步上.
What Shouldn’t Go in State
this.state 應只存放用來表達界面狀態所需要的最精簡資料, 以下幾種情況不應該將其放在狀態中:
計算後的資料 (Computed data)
不要擔心如何預處理狀態的資料, 如果你將這些計算都放在
render()裡將更容易確保你的界面一致化(不容易出錯), 舉例來說, 如果你有一個陣列類型的資料存在狀態中, 而你要用文字呈現它的數量, 比起將數量計算後存放到狀態再呈現, 只要簡單地在你的render()方法中用this.state.listItems.length + ' list items'這樣的表達式就好.組件實例 (React components)
在
render()方法裡基於props和state的資料建構它們重覆的 Properities (Duplicated data from props)
試圖用
props的當作來源資料, 而把同樣的資料放到state當作舊資料比較.