react 最近很火,翻出一篇舊文,和大家分享一下。

來源:互聯網
上載者:User

標籤:

簡介

React是Facebook開源的一個用於構建使用者介面的Javascript庫,已經 應用於Facebook及旗下Instagram。

和龐大的AngularJS不同,React專註於MVC架構中的V,即視圖。 這使得React很容易和開發人員已有的開發棧進行融合。

React順應了Web開發組件化的趨勢。應用React時,你總是應該從UI出發抽象出不同 的組件,然後像搭積木一樣把它們拼裝起來:

不過,React定義組件的方式和AngularJS截然不同。如果說HTML是一個輪子,AngularJS 的指令/Directive則是給這個輪子鑲了個金邊,而React,重新造了個輪子: JSX。

React拋棄HTML另起爐灶的原因之一是效能的考慮:DOM操作非常之慢。React引入了 虛擬DOM的概念:開發人員操作虛擬DOM,React在必要的時候將它們渲染到真正的 DOM上 —— 有點像遊戲開發中的雙緩衝區/Double Buffer幀重繪。

引入虛擬DOM的另一個好處是,容易引入不同的渲染引擎。比如將你的應用代碼渲染 到真實的DOM,或者nodejs服務端的無頭DOM,或者,iOS/Android平台組件 —— 這就是 React Native :

Hello React!

和AngularJS相比,上手React簡單到讓人震驚。

在引入React庫之後,開發API就通過React對象暴露出來了。我們要做的、能做的,就是:

在虛擬DOM上建立元素,然後將它們渲染到真實DOM上。

在範例程式碼中使用了React對象的兩個方法:

createElement(type,[props],[children…]) - 在虛擬DOM上建立指定的React元素
參數type用來指定要建立的元素類型,可以是一個字串或一個React組件類型。當使用 字串時,這個參數應當是標準的HTML標籤名稱,比如:p、div、canvas等等。

參數props是可選的JSON對象,用來指定元素的附加屬性,比如樣式、CSS類等等。 我們在樣本中簡單的設定為null。

從第三個參數children開始的所有參數,都被認為是這個元素的子項目。考慮到 虛擬DOM好歹也是DOM,容易理解React需要通過這些子項目參數,讓我們可以構造虛擬DOM樹:

var el = React.createElement(    "ul",    null,    React.createElement("li",null,"China"),    React.createElement("li",null,"Japan"),    React.createElement("li",null,"Korea"));

上面的例子在虛擬DOM中建立了一個具有三個li子項目的ul元素,看起來有點累。不過 想想,造一個輪子,總會付出一些代價的。

在樣本中,我們簡單地傳入了一個文本子項目作為p元素的內容。

  • render(element,container,[callback]) - 將虛擬DOM上的對象渲染到真實DOM上

參數element是我們使用createElement()方法建立的React元素,注意,不是HTML元素!

參數container是真實DOM中的HTML元素,作為渲染的目標容器,它的內容將被render()方法 的執行改變。

callback參數是可選的函數,當渲染完成或更新後被執行,通常我們不用它。

虛擬DOM

虛擬DOM是React的基石。

之所以引入虛擬DOM,一方面是效能的考慮。Web應用和網站不同,一個Web應用 中通常會在單頁內有大量的DOM操作,而這些DOM操作很慢。

在React中,應用程式在虛擬DOM上操作,這讓React有了最佳化的機會。簡單說, React在每次需要渲染時,會先比較當前DOM內容和待渲染內容的差異, 然後再決定如何最優地更新DOM。這個過程被稱為reconciliation。

除了效能的考慮,React引入虛擬DOM更重要的意義是提供了一種一致的開發方 式來開發服務端應用、Web應用和手機端應用:

因為有了虛擬DOM這一層,所以通過配備不同的渲染器,就可以將虛擬DOM的內容 渲染到不同的平台。而應用開發人員,使用JavaScript就可以通吃各個平台了。

相當棒的思路!

React組件

在React中定義一個組件也是相當的容易,組件就是一個 實現預定義介面的JavaScript類:

React.createClass(meta)

參數meta是一個實現預定義介面的JavaScript對象,用來 對React組件原型進行擴充。

在meta中,至少需要實現一個render()方法,而這個方法, 必須而且只能返回一個有效React元素。

這意味著,如果你的組件是由多個元素構成的,那麼你必須在外邊包一個頂層 元素,然後返回這個頂層元素。比如我們建立一個布局組件:

render:function(){    return React.createElement(        "div",null,        React.createElement("div",null,"header"),        React.createElement("div",null,"content"),        React.createElement("div",null,"footer")    );}

注意 :你的React組件名稱的首字母應當大寫, 關於大小寫差異你會在後面發現。

在範例程式碼中,我們實現了一個液晶顯示組件EzLedComp(為了更逼真一些, 定義了簡單的樣式,別忘了翻看一下),你應該會注意到div元素的樣式類是用 className而不是class聲明的,這是因為class 是JavaScript的保留字,渲染後,真實的DOM還會是:

<div class="ez-led">Hello, React!</div>

組件定義以後,和標準HTML標籤一樣,可以使用createElement()方法 建立元素,只是這時,第一個參數是我們定義的組件類,而不是標籤名字串:

React.createElement(EzLedComp);
輪子來了:JSX

React引入虛擬DOM以後,建立DOM樹得在JavaScript裡寫代碼,這使得介面定義 變得相當繁瑣。比如我們建立兩排的液晶組件得這麼寫:

render: function(){    return React.createElement(        "div",null,        React.createElement("div",{className:"ez-led"},"Hello, React!"),        React.createElement("div",{className:"ez-led"},"2015-04-15")    );}

而它們被渲染後對應的聲明式HTML則簡單明了:

<div>    <div class="ez-led">Hello, React!</div>    <div class="ez-led">2015-04-15</div></div>

這還只是兩層的樹,要是需要一棵大樹呢?

填一個坑,需要挖另一個坑。於是,JSX來了。

JSX是對JavaScript文法的擴充,它讓我們可以在JavaScript代碼中以類似HTML 的方式建立React元素。簡單的說,每當你需要使用createElement()時, 就把這個函數調用部分用渲染目標HTML替換(提醒下,不完全一致,比如class屬性 要用className代替):

//JavaScriptvar e = React.createElement(        "ul",null,        React.createElement("li",null,"China"),        React.createElement("li",null,"Japan"),    );//JSX = JavaScript + XML like extensionvar e = *   China*   Japan;

說實話,這種寫法讓代碼看起來相當鬧心。但相比寫大段的指令碼來建立DOM樹, 這至少效率高吧。好在,React不強制使用JSX,如果你是強迫症患者, 確實感覺到不舒服,那麼,可以不用它。

使用JSX

很顯然,增加了這些XML文法的指令碼不能再稱為JavaScript了,使用上 略有區別。

指定指令碼類型
在html檔案中引入的JSX指令碼,需要指定類型為text/jsx:

//內聯指令碼<script type="text/jsx">...</script>//外部指令碼<script src="a.js" type="text/jsx"></script>

引入JSX文法轉換庫
在html中使用JSX,還需要引入JSX文法轉換庫JSXTransform.js。 這個庫載入後,將在DOM樹構造完成後(通過監聽DOMContentLoaded事件)處理 JSX指令碼:

  1. 搜尋DOM樹中的script節點,如果其類型為text/jsx則進行後續處理
  2. 讀取script節點的內容,將其轉化為JavaScript代碼
  3. 構造一個新的script元素,設定其內容為轉化結果代碼,並追加到DOM樹head元素中
    JSXTransform.js引入後通過全域對象JSXTransformer提供了API介面, 我們可以使用transform()方法來類比這個文法自動轉換的過程。

在右邊的範例程式碼中,為了避免自動轉換,我們將script元素的類型設定為text/jsx2, 同時為了簡化DOM元素定位,給它加了一個id。

點擊按鈕,你就可以看到轉換結果。查看代碼,理解自動轉換的步驟。

更多的內容和免費的配套線上練習可以看這兒!

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.