React誕生的歷史原因

React誕生的原因

React是Facebook開發的一款的JS庫,那麼Facebook爲什麼要創造React?
Facebook認爲MVC無法滿足他們的擴展需求,由於他們非常巨大的代碼庫和龐大的組織,使得MVC很快變得複雜,每當需要添加一項新功能或者特性時,系統的複雜就成級數的增長,致使代碼變得脆弱而不可預測,結果導致他們的MVC正在土崩瓦解。認爲MVC不適合大規模的應用。當系統中有很多模型和相應的視圖時,其複雜度就會迅速擴大,非常難以理解和調試,特別是模型和視圖可能存在雙向數據流動。

解決這個問題需要“以某種方式組織代碼,使其更加可預測”,這通過Flux和React已經完成

Flux是一個系統架構,用於推進應用中的數據單向流動。React是一個JavaScript框架,用於構建“可預期的”和聲明式的”Web用戶界面”,它已經使Facebook更快地開發Web應用。

主要來討論React方面的問題:
React用來解決什麼問題,官方網站上這樣說道:

We build React to solve one problem:building large applications with data that changes over time.

構建數據會隨着時間改變的大型應用,React主要有以下特點:

1.簡單的表述任意時間點應用應該呈現的樣子,React就會自動管理UI界面更新當數據發生變化的時候
2.在數據發生改變時,React實際上僅僅更新了變化的一部分而已
React是關於構造可重用組件的,實際上,使用React時,我們做的更多的是構建組件。通過封裝,使得代碼複用,測試以及關注點分離更加容易。

從React官方網站上,通過《Why did we build React?》瞭解到創建React文檔的四個原因:
1.React不是一個MVC框架,React是一個構造可組合式用戶界面的庫。它鼓勵創建可重用的UI組件會隨着時間而改變的數據。
2.React不使用模板
傳統上,web應用UIs使用模板或者html指令構造。這些模板規定一套完整的抽象使你可以去構建你的UI
不同的是,React處理構建用戶界面通過將他們分解爲組件。這意味着,React使用一個真正的,全功能的編程語言去渲染視圖。
3.響應式更新非常簡單
在一個傳統的JS應用中,需要考慮數據變化然後指示DOM做出變化,使其保持最新的。甚至AngularJS,提供一個聲明式接口經由指令和數據綁定請求一個關聯的函數去手動更新DOM節點。
React採用不同的方法,當組件第一次初始化時,render方法調用,爲試圖生成一個輕量級的表現。通過這個表現,產生一個標籤字符串,然後插入文檔中。當數據變化時,render方法再次被調用。爲了儘可能有效的完成更新,我們比較值錢調用的render返回的值與新的值,然後產生一個最小的變更去應用DOM中。

render返回的數據既不是一個字符串也不是一個DOM結點。它是一個輕量級的類型,描述DOM應該是什麼樣子的。

4.HTML5僅僅是個開始
因爲React有自己輕量級的文檔表現,我們可以用它做一些很酷的事情
1.Facebook動態表格可以通過渲染取代HTML.
2.Instagram是一個’single page’網頁應用完全由React和Backbone.Router構建的。設計者可以像通常一樣使用JSX編寫React代碼。
3.我構建內部的應用雛形運行React在一個web工作站上,使用React去驅動本地ios視圖通過一個Objective-C橋。
4.你可以運行React在服務器上,便於SEO、性能、代碼分享和項目靈活性。
5.事件在全部現代瀏覽器(包括IE8)下表現一致性還有符合標準化,並且自動使用事件委派。

React的主要原理

Virtual DOM和虛擬DOM
傳統的web應用中,操作DOM一般是直接更新操作的,但是我們知道DOM更新通常是比較昂貴的。而React爲了儘可能減少對DOM的操作,提供了一種不同而有強大的方式來更新DOM,代替DOM直接操作。就是Virtual DOM,一個輕量級的虛擬DOM,就是React抽象出來的一個對象,描述DOM應該是什麼樣子,應該如何呈現。通過 這個Virtual DOM去更新更真實的DOM,而這個Virtual DOM管理真實的DOM更新。
爲什麼通過這多一層的Virtual DOM操作就能更快呢? 這是因爲React有個diff算法,更新Virtual DOM並不保證馬上影響真實的DOM,React會等到事件循環結束,然後利用這個diff算法,通過當前新的dom表述與之前的作比較,計算出最小的步驟更新真實的DOM。

React Diff

1.虛擬的DOM確保只對界面上真正發生變化的部分進行實際的DOM操作。
Web頁面是由DOM樹來構成的,當其中的某一部分發生變化時,其實就對應某個DOM節點發生了變化。在React中,構建UI界面的思路是由當前狀態決定界面。前後兩個狀態對應兩個界面,然後由react來比較兩個界面的區別。
Facebook的工程師,他們對於web界面做了兩個簡單的假設,使得Diff算法複雜程度直接降到了O(n)
1.兩個相同組件產生類似的的DOM結構,不同組件產生不同的DOM結構
2.對於同層次的一組子節點,他們可以通過唯一的id進行區分

在節點的同一位置前後輸出了不同類型的節點,React直接刪除前面的節點,然後創建並插入新的節點,刪除節點就會徹底銷燬該節點,如果該刪除的節點下有子節點,那麼這些子節點也會被完全刪除,它們也不會被用戶後面的比較

當React在同一個位置遇到不同的組件時,也是簡單的銷燬第一個組件,而把新創建的組件加上去。不同的組件一般會產生不一樣的DOM結構,與其浪費時間去比較它們的結構,他們的結構基本上是不會等價的,還不如完全創建一個新的組件上去。

2.逐層次進行節點比較
在React中,樹的算法很簡單,兩棵樹只會對同層次的節點進行比較。把之前的樹和修改之後的樹進行節點同層次的比較,React對同一個父節點下所有的子節點進行比較。當發現節點已經不存在了,就會把這個節點和它的子節點完善刪除掉,不會進行進一步的人比較,所以這樣只要遍歷一次樹,就可以完成對DOM結構的比較。

React只會考慮同層節點位置的變換,對於不同層的節點,只有簡單的刪除和創建。當根節點發現子節點中的A不見了就會直接銷燬A;而當D發現自己多了一個子節點,就會創建A作爲子節點。

爲了保持穩定的結構會有助於性能的提升,我們可以通過CSS隱藏或顯示某個節點,而不是真正的移除或者添加DOM節點。

相同類型的節點,算法比較簡單,React會對其屬性進行重設而實現節點轉換。
比如:
renderA:


renderB:

虛擬DOM的style屬性稍微不同,其值並不是一個簡單的字符串而必須是一個對象。

3.列表節點的比較:
React對於不在同一層的節點比較,即使它們完全相同,也會銷燬並重新創建,當它們在同一層的時候就要用到列表節點的Diff算法,這裏寫圖片描述


如果不設置這個li 的key值,會造成列表在更新時候的性能問題。React不能很高效的去更新這個列表

Components 組件

在DOM樹上的節點被稱爲元素,在這裏則不同,Virtual DOM上稱爲commponent。Virtual DOM的節點就是一個完整抽象的組件,它是由commponents組成。

component 的使用在 React 裏極爲重要, 因爲 components 的存在讓計算 DOM diff 更高效。

發佈了144 篇原創文章 · 獲贊 67 · 訪問量 35萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章