React提供了聲明式的API,以致於咱們不須要擔憂每次更新具體發生了什麼更改。這使得咱們開發應用變得很容易,但始終沒法清楚React內部是如何實現的。本文解釋了在 「差分算法」 中如何作出選擇,使得組件更新,在足夠快的高性能應用中仍然能夠預測。html
在理解 「差分算法」 以前,首先咱們須要去理解:node
render()
函數的做用與生命週期;ReactDOM.render()
函數的做用;import React from "react";
import ReactDOM from 'react-dom';
const First = () => (<div> <h1>第一棵樹</h1> <div>附加信息</div> </div>);
const Second = () => (<div> <h1>第二棵樹</h1> <Third /> </div>);
const Third = () => (<div> <h1>第三棵樹</h1> <div>附加信息</div> </div>);
const App = () => (<div> <First /> <Second /> </div>);
ReactDOM.render(<App />, document.getElementById('root')); 複製代碼
萬變不離其宗,對於一個HTML頁面,document與Node永遠會是它的基礎組成部分(實際上document也只是一個特別的Node),若是把document看作一張紙,那麼Node能夠當作點綴在紙上的文字、圖片或符號。react
在React中,React組件是由真實的Dom Node組成,最終會被轉化爲Dom Node並在document中渲染出來(事件\樣式\選擇器,只屬於真實的DOM Node)。算法
當你使用React的時候,你能夠認爲:瀏覽器
render()
函數都建立了一棵React元素樹。render()
函數,見下文。HTMLElement
組成,便是 —— 每一棵樹均可以做爲另外一棵樹的子樹,正如上圖所示:<Third />是<Second />的子樹,<Second />和<First />又都是<App />的子樹。ReactDOM.render(element, container[, callback])
將這棵樹掛載到容器(container)
中。容器(container)
,不過是document中某個指定的Div或其它塊級元素。JavaScript選擇器
仍是dom操做插件
仍是React提供的Refs
,對Dom node的操做都會被保留在這個document中,並在組件的state
或props
發生改變的時候參與 「差分算法」。對於Function組件(無狀態組件)
就是自身,對於Class組件(有狀態組件)
就是從React.Component
繼承的render()
方法。服務器
當render()
被調用時,能夠依賴props
和state
來構造返回值,其返回值類型包括以下:cookie
<div />
、<MyComponent />
render()
必須返回單元素(single),React提供了<></>和<React.Fragment>容許開發者從render()
中返回多元素test && <Child />
,這裏test
是布爾值(boolean)render()
應該是一個純函數,返回值只依賴於state
和props
,而且不會產生反作用,反作用包括:網絡
state
和props
Date.now()
或 Math.random()
setTimeout()
、console.log()
若是你須要瀏覽器交互或網絡請求,能夠選擇在componentDidMount()
或其它合適的聲明周期函數中執行。有些條件沒有作硬性要求,可是保證render()
做爲純函數,可以提升組件更新的性能。session
組件在掛載(Mounting)和更新(Updating)時,render()
都會被執行,併產生一棵新的React元素樹。聲明週期執行順序以下。詳情可見官方文檔《component-lifecycle》dom
render()
會產生一棵新的樹,這顆新樹會被直接掛載到父組件對應的那棵樹上。
render()
會產生一棵新的樹,而後與先前的那棵舊樹,執行 「 差分算法」 更新UI(用戶界面)。
ReactDOM.render(element, container[, callback])
複製代碼
該方法將整個React元素樹渲染到document中指定的<Div />
容器中,並返回根組件(對應最大元素樹)的引用(Function 組件 —— 無狀態組件,沒有實例(Instance)因此返回null)。
若是這個React元素(根組件)先前已經被渲染到容器中,那麼將對它執行更新,按照 「差分算法」 去呈現它。
若是這個可選的參數—— 回調函數,被提供。那麼會在組件被渲染或更新後調用。
ReactDOM.render()
控制着容器(container)節點的內容,第一次調用時,任何存在的Dom元素都會被替換,以後再調用會使用React Dom diffing algorithm(差分算法)進行高效更新。ReactDOM.render()
不修改容器節點(只修改容器的子節點)。ReactDOM.render()
當前返回根組件(root ReactComponent )實例的引用。然而,返回值的使用已經被遺留了,應該避免去使用它,由於在將來的React版本中,在某些狀況下React會採用異步的方式去渲染組件。若是你真的須要引用根組件實例,首選解決方案是爲你的根組件添加《callback ref》。ReactDOM.render()
去融合服務端渲染容器(server-rendered container)已經被遺棄了,並將在React 17被移除,代替使用hydrate()。