我們已經(jīng)學(xué)習(xí)如何使用 React 顯示數(shù)據(jù)?,F(xiàn)在讓我們來學(xué)習(xí)如何創(chuàng)建交互式界面。
var LikeButton = React.createClass({ getInitialState: function() { return {liked: false}; }, handleClick: function(event) { this.setState({liked: !this.state.liked}); }, render: function() { var text = this.state.liked ? 'like' : 'haven\'t liked'; return ( <p onClick={this.handleClick}> You {text} this. Click to toggle. </p> ); } }); React.render( <LikeButton />, document.getElementById('example') );
React 里只需把事件處理器(event handler)以駱峰命名(camelCased)形式當(dāng)作組件的 props 傳入即可,就像使用普通 HTML 那樣。React 內(nèi)部創(chuàng)建一套合成事件系統(tǒng)來使所有事件在 IE8 和以上瀏覽器表現(xiàn)一致。也就是說,React 知道如何冒泡和捕獲事件,而且你的事件處理器接收到的 events 參數(shù)與 W3C 規(guī)范 一致,無論你使用哪種瀏覽器。
在幕后,React 做了一些操作來讓代碼高效運(yùn)行且易于理解。
Autobinding: 在 JavaScript 里創(chuàng)建回調(diào)的時(shí)候,為了保證 this
的正確性,一般都需要顯式地綁定方法到它的實(shí)例上。有了 React,所有方法被自動(dòng)綁定到了它的組件實(shí)例上。React 還緩存這些綁定方法,所以 CPU 和內(nèi)存都是非常高效。而且還能減少打字!
事件代理 : React 實(shí)際并沒有把事件處理器綁定到節(jié)點(diǎn)本身。當(dāng) React 啟動(dòng)的時(shí)候,它在最外層使用唯一一個(gè)事件監(jiān)聽器處理所有事件。當(dāng)組件被加載和卸載時(shí),只是在內(nèi)部映射里添加或刪除事件處理器。當(dāng)事件觸發(fā),React 根據(jù)映射來決定如何分發(fā)。當(dāng)映射里處理器時(shí),會(huì)當(dāng)作空操作處理。參考David Walsh 很棒的文章 了解這樣做高效的原因。
React 把用戶界面當(dāng)作簡單狀態(tài)機(jī)。把用戶界面想像成擁有不同狀態(tài)然后渲染這些狀態(tài),可以輕松讓用戶界面和數(shù)據(jù)保持一致。
React 里,只需更新組件的 state,然后根據(jù)新的 state 重新渲染用戶界面(不要操作 DOM)。React 來決定如何最高效地更新 DOM。
常用的通知 React 數(shù)據(jù)變化的方法是調(diào)用 setState(data, callback)
。這個(gè)方法會(huì)合并(merge) data
到 this.state
,并重新渲染組件。渲染完成后,調(diào)用可選的 callback
回調(diào)。大部分情況下不需要提供 callback
,因?yàn)?React 會(huì)負(fù)責(zé)把界面更新到最新狀態(tài)。
大部分組件的工作應(yīng)該是從 props
里取數(shù)據(jù)并渲染出來。但是,有時(shí)需要對(duì)用戶輸入、服務(wù)器請(qǐng)求或者時(shí)間變化等作出響應(yīng),這時(shí)才需要使用 State。
嘗試把盡可能多的組件無狀態(tài)化。 這樣做能隔離 state,把它放到最合理的地方,也能減少冗余并,同時(shí)易于解釋程序運(yùn)作過程。
常用的模式是創(chuàng)建多個(gè)只負(fù)責(zé)渲染數(shù)據(jù)的無狀態(tài)(stateless)組件,在它們的上層創(chuàng)建一個(gè)有狀態(tài)(stateful)組件并把它的狀態(tài)通過 props
傳給子級(jí)。這個(gè)有狀態(tài)的組件封裝了所有用戶的交互邏輯,而這些無狀態(tài)組件則負(fù)責(zé)聲明式地渲染數(shù)據(jù)。
State 應(yīng)該包括那些可能被組件的事件處理器改變并觸發(fā)用戶界面更新的數(shù)據(jù)。 真實(shí)的應(yīng)用中這種數(shù)據(jù)一般都很小且能被 JSON 序列化。當(dāng)創(chuàng)建一個(gè)狀態(tài)化的組件時(shí),想象一下表示它的狀態(tài)最少需要哪些數(shù)據(jù),并只把這些數(shù)據(jù)存入 this.state
。在 render()
里再根據(jù) state 來計(jì)算你需要的其它數(shù)據(jù)。你會(huì)發(fā)現(xiàn)以這種方式思考和開發(fā)程序最終往往是正確的,因?yàn)槿绻?state 里添加冗余數(shù)據(jù)或計(jì)算所得數(shù)據(jù),需要你經(jīng)常手動(dòng)保持?jǐn)?shù)據(jù)同步,不能讓 React 來幫你處理。
this.state
應(yīng)該僅包括能表示用戶界面狀態(tài)所需的最少數(shù)據(jù)。因些,它不應(yīng)該包括:
計(jì)算所得數(shù)據(jù): 不要擔(dān)心根據(jù) state 來預(yù)先計(jì)算數(shù)據(jù) —— 把所有的計(jì)算都放到 render()
里更容易保證用戶界面和數(shù)據(jù)的一致性。例如,在 state 里有一個(gè)數(shù)組(listItems),我們要把數(shù)組長度渲染成字符串, 直接在 render()
里使用 this.state.listItems.length + ' list items'
比把它放到 state 里好的多。
React 組件: 在 render()
里使用當(dāng)前 props 和 state 來創(chuàng)建它。
基于 props 的重復(fù)數(shù)據(jù): 盡可能使用 props 來作為惟一數(shù)據(jù)來源。把 props 保存到 state 的一個(gè)有效的場景是需要知道它以前值的時(shí)候,因?yàn)槲磥淼?props 可能會(huì)變化。
更多建議: