虛擬DOM的創(chuàng)建過程##
image.png
- 我們通過React.createElement最終創(chuàng)建出來一個ReactElement對象圈纺,函數(shù) -> 對象链沼。
原因是React利用ReactElement對象(JS對象體現(xiàn))組成了一個JS的對象樹,JS的對象樹就是虛擬DOM沛鸵。
image.png
- 我們將babel轉義過的jsx語法通過控制臺輸出括勺。結果如上圖。
image.png
直接輸出jsx語法曲掰,與步驟2結果相同疾捍。
對象層層展開,通過props.children栏妖,和我們的dom結構一致乱豆。如何轉為真實dom。
通過ReactDOM.render(<>,document.getElementById("app")); 函數(shù)將js對象映射到對應的app吊趾。過程總結
// jsx -> createElement函數(shù) -> ReactElement(對象樹) -> ReactDOM.render -> 真實dom
// native
// jsx -> createElement函數(shù) -> ReactElement(對象樹) -> ReactDOM.rener -> 原生控件(UIButton/Button)
- 為什么不直接修改真實DOM而使用虛擬DOM
- 很難跟蹤狀態(tài)發(fā)生的改變:原有開發(fā)模式中難以跟蹤狀態(tài)改變宛裕,不易調試。(調試方式论泛,debug && 打涌)。在react工具中可以對dom狀態(tài)進行跟蹤屁奏。
- 操作真實DOM性能較低:
第一點:document.createElement本身創(chuàng)建出來的就是一個非常復雜的對象岩榆。
第二點:DOM操作會引起瀏覽器的回流和重繪,性能損耗非常大。
舉個例子:一組數(shù)字[0,1,2,3,4]勇边,通過ul和li展示出來犹撒,后來又增加5條數(shù)據(jù)[0,1,2,3,4,5,6,7,8,9]。
可以通過重新遍歷數(shù)組(先移除掉)粒褒。
或在ul后面追加另外5個li來重新渲染识颊,如下圖進行了5次遍歷,意味著5次dom操作怀浆,效率很低谊囚。
image.png
最好的方法:對批量的操作進行合并,比如可以通過DocumentFragment進行合并执赡。我們正是通過镰踏,先在虛擬DOM上面來更新,再將其更新渲染到真實dom上面沙合,從而解決上面問題奠伪,避免重復操作真實DOM。
React官網關于Virtual DOM的說法:
虛擬dom是編程理念首懈,UI以虛擬化的表現(xiàn)形式(相對簡單的JS對象)被保存于內存中绊率,并通過如ReactDOM.render
等類庫使虛擬DOM與真實DOM同步,這一過程叫做協(xié)調Reconciliation究履。
虛擬DOM幫我們從命令式編程轉到了聲明式編程的模式滤否,與React元素關聯(lián)在一起,都代表了用戶界面的對象最仑,而React也使用一個名為“fibers”的內部對象來存放組件樹的附加信息藐俺,兩者被認為是虛擬DOM的一部分實現(xiàn)。
元素位置改變之類都會引起重排泥彤。