鍍金池/ 教程/ HTML/ 動態(tài)交互式用戶界面
顯示數(shù)據(jù)
組件的引用
Controlled Input 值為 null 的情況
Reconciliation
子 props 的類型
組件的詳細(xì)說明和生命周期
傳遞 Props
特殊的非 DOM 屬性
組件 API
PureRenderMixin
雙向綁定輔助工具
瀏覽器中的工作原理
深入 JSX
表單組件
Dangerously Set innerHTML
入門
JSX 中的 If-Else
克隆組件
教程
更多的關(guān)于Refs
JSX 的 false 處理
高級性能
Mounting 后 componentWillReceiveProps 未被觸發(fā)
簡介
測試工具集
JSX 陷阱
工具集成(ToolingIntegration)
公開組件功能
通過 AJAX 加載初始數(shù)據(jù)
事件系統(tǒng)
可復(fù)用組件
this.props.children undefined
不可變數(shù)據(jù)的輔助工具(Immutability Helpers)
動態(tài)交互式用戶界面
組件的 DOM 事件監(jiān)聽
復(fù)合組件
動畫
插件
JSX 展開屬性
行內(nèi)樣式
性能分析工具
類名操作
與其他類庫并行使用 React
鍵控的片段
標(biāo)簽和屬性支持
組件間的通信
React (虛擬)DOM 術(shù)語
JSX 根節(jié)點(diǎn)的最大數(shù)量
在樣式props中快速制定像素值
頂層 API
深入理解 React
自閉合標(biāo)簽
為什么使用 React?
getInitialState 里的 Props 是一個反模式
與 DOM 的差異

動態(tài)交互式用戶界面

我們已經(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')
);

事件處理與合成事件(Synthetic Events)

React 里只需把事件處理器(event handler)以駱峰命名(camelCased)形式當(dāng)作組件的 props 傳入即可,就像使用普通 HTML 那樣。React 內(nèi)部創(chuàng)建一套合成事件系統(tǒng)來使所有事件在 IE8 和以上瀏覽器表現(xiàn)一致。也就是說,React 知道如何冒泡和捕獲事件,而且你的事件處理器接收到的 events 參數(shù)與 W3C 規(guī)范 一致,無論你使用哪種瀏覽器。

幕后原理:自動綁定(Autobinding)和事件代理(Event Delegation)

在幕后,React 做了一些操作來讓代碼高效運(yùn)行且易于理解。

Autobinding: 在 JavaScript 里創(chuàng)建回調(diào)的時候,為了保證 this 的正確性,一般都需要顯式地綁定方法到它的實(shí)例上。有了 React,所有方法被自動綁定到了它的組件實(shí)例上。React 還緩存這些綁定方法,所以 CPU 和內(nèi)存都是非常高效。而且還能減少打字!

事件代理 : React 實(shí)際并沒有把事件處理器綁定到節(jié)點(diǎn)本身。當(dāng) React 啟動的時候,它在最外層使用唯一一個事件監(jiān)聽器處理所有事件。當(dāng)組件被加載和卸載時,只是在內(nèi)部映射里添加或刪除事件處理器。當(dāng)事件觸發(fā),React 根據(jù)映射來決定如何分發(fā)。當(dāng)映射里處理器時,會當(dāng)作空操作處理。參考 David Walsh 很棒的文章 了解這樣做高效的原因。

組件其實(shí)是狀態(tài)機(jī)(State Machines)

React 把用戶界面當(dāng)作簡單狀態(tài)機(jī)。把用戶界面想像成擁有不同狀態(tài)然后渲染這些狀態(tài),可以輕松讓用戶界面和數(shù)據(jù)保持一致。

React 里,只需更新組件的 state,然后根據(jù)新的 state 重新渲染用戶界面(不要操作 DOM)。React 來決定如何最高效地更新 DOM。

State 工作原理

常用的通知 React 數(shù)據(jù)變化的方法是調(diào)用 setState(data, callback)。這個方法會合并(merge) datathis.state,并重新渲染組件。渲染完成后,調(diào)用可選的 callback 回調(diào)。大部分情況下不需要提供 callback,因?yàn)?React 會負(fù)責(zé)把界面更新到最新狀態(tài)。

哪些組件應(yīng)該有 State?

大部分組件的工作應(yīng)該是從 props 里取數(shù)據(jù)并渲染出來。但是,有時需要對用戶輸入、服務(wù)器請求或者時間變化等作出響應(yīng),這時才需要使用 State。

嘗試把盡可能多的組件無狀態(tài)化。 這樣做能隔離 state,把它放到最合理的地方,也能減少冗余并,同時易于解釋程序運(yùn)作過程。

常用的模式是創(chuàng)建多個只負(fù)責(zé)渲染數(shù)據(jù)的無狀態(tài)(stateless)組件,在它們的上層創(chuàng)建一個有狀態(tài)(stateful)組件并把它的狀態(tài)通過 props 傳給子級。這個有狀態(tài)的組件封裝了所有用戶的交互邏輯,而這些無狀態(tài)組件則負(fù)責(zé)聲明式地渲染數(shù)據(jù)。

哪些 應(yīng)該 作為 State?

State 應(yīng)該包括那些可能被組件的事件處理器改變并觸發(fā)用戶界面更新的數(shù)據(jù)。 真實(shí)的應(yīng)用中這種數(shù)據(jù)一般都很小且能被 JSON 序列化。當(dāng)創(chuàng)建一個狀態(tài)化的組件時,想象一下表示它的狀態(tài)最少需要哪些數(shù)據(jù),并只把這些數(shù)據(jù)存入 this.state。在 render() 里再根據(jù) state 來計(jì)算你需要的其它數(shù)據(jù)。你會發(fā)現(xiàn)以這種方式思考和開發(fā)程序最終往往是正確的,因?yàn)槿绻?state 里添加冗余數(shù)據(jù)或計(jì)算所得數(shù)據(jù),需要你經(jīng)常手動保持?jǐn)?shù)據(jù)同步,不能讓 React 來幫你處理。

哪些 不應(yīng)該 作為 State?

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 里有一個數(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 的一個有效的場景是需要知道它以前值的時候,因?yàn)槲磥淼?props 可能會變化。
上一篇:入門下一篇:與 DOM 的差異