React/虛擬DOM

在說虛擬DOM以前,先來一個引子,從輸入url到展示出整個頁面都有哪些過程?javascript

一、輸入網址html

二、DNS解析java

三、創建tcp鏈接react

四、客戶端發送HTPP請求算法

五、服務器處理請求 編程

六、服務器響應請求api

七、瀏覽器展現HTML瀏覽器

八、瀏覽器發送請求獲取其餘在HTML中的資源。性能優化

其中瀏覽器展現HTML通過了:構建DOM樹,解析CSS構建CSSOM樹,DOM與CSSOM結合成爲RenderObject樹,而後將RenderObject樹渲染成頁面(佈局->重繪),這個過程是由渲染引擎作的,JavaScript引擎與渲染引擎是獨立的,由於js能夠操做dom,因此渲染引擎會暴露給js引擎一些接口來操做dom元素,這個通訊過程的耗費是比較大的,因此在性能優化中會有一條:js儘可能少操做dom元素,而虛擬DOM則是爲了解決這一問題而出現。服務器

當你用傳統的源生api或jQuery去操做DOM時,瀏覽器會從構建DOM樹開始從頭至尾執行一遍流程。好比當你在一次操做時,須要更新10個DOM節點,理想狀態是一次性構建完DOM樹,再執行後續操做。但瀏覽器沒這麼智能,收到第一個更新DOM請求後,並不知道後續還有9次更新操做,所以會立刻執行流程,最終執行10次流程。顯然例如計算DOM節點的座標值等都是白白浪費性能,可能此次計算完,緊接着的下一個DOM更新請求,這個節點的座標值就變了,前面的一次計算是無用功。

虛擬DOM就是爲了解決這個瀏覽器性能問題而被設計出來的。例如前面的例子,假如一次操做中有10次更新DOM的動做,虛擬DOM不會當即操做DOM,而是將這10次更新的diff內容保存到本地的一個js對象中,最終將這個js對象一次性attach到DOM樹上,通知瀏覽器去執行繪製工做,這樣能夠避免大量的無謂的計算量。

什麼是虛擬DOM?

Virtual DOM 是一種編程概念。在這個概念裏, UI 以一種理想化的,或者說「虛擬的」表現形式被保存於內存中,並經過如 ReactDOM 等類庫使之與「真實的」 DOM 同步。這一過程叫作協調

在某一時間節點調用 React 的 render() 方法,會建立一棵由 React 元素組成的樹。在下一次 state 或 props 更新時,相同的 render() 方法會返回一棵不一樣的樹。React 須要基於這兩棵樹之間的差異來判斷如何有效率的更新 UI 以保證當前 UI 與最新的樹保持同步。(Diffing算法)

這種方式賦予了 React 聲明式的 API:您告訴 React 但願讓 UI 是什麼狀態,React 就確保 DOM 匹配該狀態。這使您能夠從屬性操做、事件處理和手動 DOM 更新這些在構建應用程序時必要的操做中解放出來。

如何建立虛擬dom   

JSX就是在建立虛擬DOM,JSX就是React.createElement(component, props, ...children)的語法糖

<MyButton color="blue" shadowSize={2}>
  Click Me
</MyButton>

 會被babel轉譯成

React.createElement(
  MyButton,
  {color: 'blue', shadowSize: 2},
  'Click Me'
)

 React.createElement() 會預先執行一些檢查,以幫助你編寫無錯代碼,但實際上它建立了一個這樣的對象:

// 注意:這是簡化過的結構
const element = {
  type: 'h1',
  props: {
    className: 'greeting',
    children: 'Hello, world!'
  }
};

  也就是=》react元素

ReactDOM

ReactDOM.render  把虛擬dom轉成真實dom,而且掛載

 

ReactDOM.render會返回對根組件 ReactComponent 實例的引用,可是目前應該避免使用返回的引用,在將來版本的 React 中,組件渲染在某些狀況下可能會是異步的。 若是你真的須要得到對根組件 ReactComponent 實例的引用,那麼推薦爲根元素添加 callback ref
 
首次調用時,容器節點裏的全部 DOM 元素都會被替換,後續的調用則會使用 React 的 DOM 差分算法(DOM diffing algorithm)進行高效的更新。
 

 ReactDOM.render() 不會修改容器節點(只會修改容器的子節點)。

相關文章
相關標籤/搜索