React學習報告

React原理學習

React出身FaceBook豪門,一出生就帶着virtualDOM和diff算法兩大顛覆式的被動技能,很快引來高度關注,而且以高效快速著稱。
通過一段時間的使用,抽出時間來學習其原理,發現並不難,可是想法很創新。造就了其不一樣於傳統框架的開發模式。html

1、VirtualDOM

VirtualDOM一直是React最著名,最神祕的特色。也是其高效迅速的核心。
virtualDOM其實很好理解:FaceBook的工程師認爲傳統的框架,頻繁的操做DOM代價很大。性能和速度很低,想找一種東西替代DOM,但又能有DOM的嵌套結構和屬性。因而FaceBook工程師們創造出virtualDOM。本質上virtualDOM就是一個json對象,用來描述真實DOM應有的屬性和子集。擁有和DOM同樣的嵌套關係造成的virtualDOM樹。前端

舉個例子:咱們有一段HTMLvue

<div id="wrap">
    <div class="box1" style="margin-left: 10px;padding-top: 10px;"></div>
    <div class="box2">
        <span data-name='box'>this is a box</span>
    </div>
</div>

上述是一段很簡單的有嵌套關係的HTML,咱們能夠看到裏面有幾個關鍵屬性,其實只須要記住這幾個關鍵屬性,咱們就至關於知道了整段節點。
根據上述HTML,抽象出來的該節點的關鍵屬性。react

var conatiner = {
    tagName: 'div',
    id: 'wrap',
    children: [box1, box2]
};

var box1 = {
    tagName: 'div',
    className: 'box1',
    style: {marginLeft: '10px', paddingTop: '10px'},
    children: []
}

var box2 = {
    tagName: 'div',
    className: 'box2',
    children: [text]
};

var text = {
    tagName: 'span',
    'data-name': 'box', // 自定義屬性
    text: 'this is a box'
    children: []
};

上面的HTML裏面真正有用的信息僅僅幾行代碼就能夠描述。React作的其實就是反向繪製。git

一個真實節點有不少屬性,可是不少屬性是繪製DOM相關的(好比offset,scrollTop這種,節點渲染以後添加的跟節點樣式相關的屬性)。virtualDOM對這些不常見屬性暫不考慮(實際上這些繪製DOM的屬性都在react-dom中),抽出重要的屬性,以及嵌套關係記錄下來(高效),放到內存中(迅速),這樣減小了不少用不到的屬性。 當virtualDOM樹生成出來以後,只要按照特意的方法解析(JSX),就會快速的生成出DOM了。
以上大概就是React誕生的緣由和核心原理。github

2、diff算法

另外一個著名的特色就是神祕的diff算法。這個算法也不難,甚至以爲並不如宣傳的那麼牛*還有些失望。可是仍是比較麻煩的。
diff算法主要是用來判斷兩個virtualDOM樹差別的,目的是以最小的代價去更新樹。
當特定情境發生須要更改DOM的時候,React並不認爲直接操做DOM是最好的選擇。他認爲不管是簡單的DOM操做仍是複雜的DOM操做,都應由改動前的virtualDOM和改動後的virtualDOM計算出來,而後根據計算結果再去渲染DOM。這樣至關因而計算出每次操做DOM的最優算法
舉個例子 須要移動火材棍使等式成立算法

clipboard.png

圖1-移動火材棍使等式成立示意圖json

普通狀況下你們直接將4個火材棍移到最前,兩個火材棍移到中間,這樣4-2=2等式成立。
聰明一點的人發現只須要移動中間的兩個火材棍到最左,便可使等式成立。這樣代價更小。
React通過計算髮現:原來只須要移動"="的一個火材棍到"-"便可使等式成立2=4-2這樣代價最小。
diff算法就是這樣的一套標準化計算流程,其告訴React每次變化如何更改DOM代價最小,或者直接從新渲染性能最優。redux

3、State

React的另外一個創新思惟就是數據爲中心。這也是現代前端框架廣泛的思想。
如今渲染DOM也不用咱們來管了,操做DOM也不用咱們來管了那咱們來管什麼?
咱們須要管理數據,告訴React什麼使用,應該有什麼樣的DOM。
React是根據virtualDOM來渲染DOM的,那virtualDOM是根據什麼生成的?答案就是state
React關鍵點就是state改變,就會從新渲染DOM,這樣只須要將影響頁面的數據放到state中。設置好什麼時候如何觸發修改state,剩下的React就會自動完成。數組

4、JSX

JSX能夠說也是React的核心部分。它使用XML的標記方式直接去聲明界面,組件界面間能夠嵌套。
JSX最鮮明的特徵就是,script標籤中聲明text屬性爲text/babel,這樣調用babel解釋器。
上面是官方的說法用通俗的話說就是:JSX其實就是一個爲了使咱們方便使用React發明的一種轉義工具。
包括在下面的例子中,咱們能夠看到例子中的語法跟正常使用的語法不一樣,就是由於babel。React原始的語法是不支持咱們如今使用組件嵌套的,好比down下React官方推薦的demo,第二個例子中的源代碼以下:

clipboard.png

圖2-使用JSX語法編寫示例

能夠看到Counter組件的render方法return出了一個button組件。
若是打開React官方demo的第一個例子,會發現語法徹底不一樣。

clipboard.png

圖3-使用React語法編寫示例

能夠看到原始的React語法是不支持組件嵌套的。甚至是不支持return <div><div>的。render方法return的只能是虛擬DOM。

5、React渲染過程研究

React如何將用戶輸入的代碼實現成真實DOM,是接下來要研究的問題。大體過程能夠分爲首次渲染和再次渲染。

clipboard.png

圖4-React渲染機制示意圖

上圖是整理出來的React渲染機制的流程圖,左邊的首次渲染的過程,右邊是再次渲染的過程。這裏主要講解下該圖。

1.首次渲染

咱們在使用React的時候,每每定義不少組件,組件輸出的DOM中,還有自定義組件。
在JS最後,使用ReactDOM.render(element, container);將定義好的組到一個容器中。
咱們能夠將首次渲染過程分爲如下幾步:

  1. React首先對咱們定義組件進行解析 解析後的每一個組件的返回結果其實就是一個個virtualDOM 每一個virtualDOM中都會有children屬性保存其子節點 這樣根節點解析後 會產生一個完整的virtualDOM樹。

  2. React.render解析根節點virtualDOM 進而解析整個virtualDOM樹(在React1.0以後 React拆分紅React和React-dom 如今都使用ReactDOM.render)

  3. React.render將virtualDOM傳遞給組件工廠 工廠斷定virtualDOM具體類別進行具體解析 好比React將virtualDOM分爲三類:文本節點 瀏覽器自帶元素和自定義組件 每一個類的virtualDOM都有各自對應的component類進行解析 如上圖

  4. 將每一個virtualDOM解析以後 調用各自component類的mountComponent方法 將virtualDOM翻譯成真實DOM 並將其事件掛載到Document對象上

  5. 將整個virtualDOM翻譯的真實DOM掛載到容器中

  6. 觸發mount事件

這樣就完成了首次渲染的邏輯,能夠看到首次渲染的邏輯仍是比較簡單,就是整理出定義的關鍵屬性和嵌套關係成virtualDOM,按照virtualDOM進行繪製真實DOM,輸出到掛載點上。
能夠看一個簡單的例子:

clipboard.png
圖5-React首次渲染實例-代碼

clipboard.png
圖6-React首次渲染實例-顯示

在上面的例子中咱們能夠看到,定義了一個block和Box。React.createElement的第三個參數就是其子節點數組,box有三個block子節點和一個文本節點。最後將輸出的DOM掛載到container上,顯示如預期同樣。咱們再來看看在此渲染的過程:

2.再次渲染(reRender)

  1. 每次調用setState方法,都會調用該組件receiveComponent方法。

  2. receiveComponent方法修改state而且判斷,更改state後DOM是否發生修改,是的話diff算法實現最小更新。

  3. 渲染完成 調用hook函數componentDidUpdate。

這裏再次渲染過程很簡單,可是是最複雜的過程。每次渲染完成時virtualDOM樹會繼續保存在內存中, 在更改state等狀況下直接使用。 三種不一樣類型的節點,有着不一樣的更改方法:好比文本節點直接替換 瀏覽器自帶元素使用diff算法複雜計算。
React節點會有一個key屬性,該屬性就是React進行diff計算的。key上攜帶者嵌套,索引等相關信息。 diff算法中會遞歸找出virtualDOM樹中的差異,組裝成差別對象,添加到更新隊列,在合適的時機進行更新。
以上就是React渲染機制的大體過程,至於diff算法這裏暫不介紹,下面參考連接有詳細介紹。

React優點和劣勢

2013年React開源,做爲目前較火的現代前端框架它有哪些優勢和缺點,也是咱們能夠了解。在衆多框架中選型的重要參考。
目前較流行的框架有angular、vue等,下面橫向做對比分析其優缺點。

1. Angular

Angular是09年google工程師建立的。做爲劃時代的前端框架,其創新性的使用指令系統和MVVM框架
優勢:
豐富的指令系統,強大的指令系統是的開發者能夠有不少方便的使用方法供選擇;
較完善的MVVM框架,包含模板、路由、雙向數據綁定、模塊化、服務、過濾器、依賴注入等全部功能;
google去維護,用戶數多,社區強大。
缺點:
太過繁雜的指令系統,提升了學習成本。
渲染速度太慢,有人作過測試以下圖:

clipboard.png
圖中表示不一樣框架每秒能渲染的操做數,越長表明性能越好。可見angular基本排在最後。
angular2對比angular1斷崖式升級,對開發者形成很高的學習成本。

2. Vue

Vue是近些年最火爆的框架(國內)。尤爲在做者尤大加入到阿里後,vue在國內的影響力和推廣力更強。
優勢:
渲染效率差很少是React的10倍;
結合Angular和React的優勢,有模板、有virtualDOM、有過濾器和指令系統。上手簡單,十分方便。
缺點:
新生兒。做者16加入阿里,維護和社區方面跟其餘兩個框架比,不是很強大。
不支持IE8。(??什麼是IE8??)

3. React

主角來了。通過幾年的發展,你們的實踐,React也是愈來愈完善。不斷推出的React邪教全家桶(router redux RN等)也是漸漸豐富了React的生態。
優勢:
思想新穎,影響了vue等框架;
FaceBook是他親爹,不少大型項目都在用,完善的維護和強大的社區(國外各類追捧)。
缺點:
新穎的思惟,形成了其須要理解實現過程,上手成本較高;
對動畫效果支持不是很好;
不是MV框架,只負責UI繪製須要學習全家桶來實現MV框架。

參考文獻:

  1. reactjs源碼分析-上篇(首次渲染實現原理)

  2. reactjs源碼分析-下篇(更新機制實現原理)

  3. Angular Vue React 渲染實現比較

  4. ARV 渲染實現比較之 Angular

  5. 對比其餘框架 - Vue.js

  6. vue,angular,avalon這三種MVVM框架之間有什麼優缺點?

相關文章
相關標籤/搜索