虛擬dom(下面簡化稱為vnode)簡而言之 ,就是用js去描述一個dom節點樹,而dom變化的對比,都放在js層來做。
傳統的dom節點,是這樣的
>
classname='text'>寫個啥內容
>
vnode是長這樣的
, //屬性鍵值對
children:, //子節點
key:undefined, //節點的唯一值
...
}
為什麼需要vnode?
這裡,我們來引入一個傳統的操作dom栗子。
var arr = [1,2,3,4]
function render(data)
var ul= createelement('ui')
data.foreach((elem)=>)
return ul
}render(arr)
輸出列印的結果是:
但是這樣操作dom的結果,當專案越大,頁面互動越複雜,頻繁的去操作dom,會導致頁面卡頓,效能差,如何去減少dom操作是效能優化的一個關鍵點。
千呼萬喚的,vnode可以解決這樣的問題!!!
vnode是vue和react的核心。將dom對比操作放在js層,提高效率。如何使用vnode?
首先vdom的兩個核心apih是指hyperscript,一種可以通過js來建立html的庫。
>
classname='text'>寫個啥內容
>
//經過babel編譯,然後將它們傳遞給h函式呼叫
h( 'div',
null,
h('p',,'寫個啥內容啊')
)//react的react.createelement函式的作用就跟這裡的h函式一樣,結果是為了獲得一個vnode,虛擬節點
h函式輸出的元素是一個dom節點的js物件,類似這樣
,
'children':[...],
'key':undefined,
...}
h函式結束後,會呼叫render函式啦!!!
前面我們提到了jsx是如何轉換為虛擬dom的js物件,那麼虛擬dom又是如何轉為真實的dom?這裡需要思考兩個問題:
寫過react的人都知道,我們每個元件中有且只有一個render方法
//class方式建立的元件
class home extends react.component
}// 函式申明建立的元件
function page()
以上的**栗子容易看出,無論是class方式還是函式申明方式建立出來的元件,返回的有且只有一個頂點節點。呼叫render方法,可以將react元素渲染到真實的dom中。
在元件例項化和存在期時會執行render。
從下圖中可以看出:
同樣,在purecomponent中,只接受props和state引數,如果props和state沒有改變,purecomponent不會重渲染,可以一定程度上減少了render帶來的消耗。
前面提到,react的核心虛擬dom可以講真實的dom節點以obj物件的形式來表示,通過對比新舊的obj物件的差異,更改頁面相對應的變化節點。而react.render實際上就相當於是vdom裡面的path函式,path函式接收兩個引數。
以下例子,建立一個節點的實現思路(簡易的)
var vnode
function render(data),
children:[…]}*/
if(vnode)else
// 將舊節點儲存起來,便於下次新節點的新舊對比
vnode = newvnode
}
第一次渲染是如何進行?
path(container,newvnode)
// 建立一個真實節點
function createelement(vnode)
var elem = document.createelement(tag) // 建立一個真實的dom節點
for(attrname in attrs)
}children.foreach(function(childvode))
return elem
}
再次渲染是如何進行?
path(vnode,newvnode)
//更新渲染,通過對比新舊vnode,更新節點樹
function updatechildren (vnode,newvnode)
if(child.tag === newchild.tag)else })}
path(container,vnode)和path(vnode,newvnode)的實現也是diff演算法的一個實現過程,通過呼叫createelement和updatechildren方法讓頁面上的節點建立和更新。
當然,真正的diff演算法是非常複雜的。
這一節的主要講的render函式在react中的一個工作過程,減少和控制不必要的重複渲染可以有效的提高頁面效能。
DOM和BOM
dom全稱 document object model 文件物件模型 通過dom將html文件轉化為物件模型,操作整個網頁。dom分為htm...
Refs 和 DOM
在常規的 react 資料流中,props 是父元件與子元件互動的唯一方式。要修改子元素,你需要用新的 props 去重新渲染子元素。然而,在少數情況下,你需要在常規資料流外強制修改子元素。被修改的子元素可以是 react 元件例項,或者是一個 dom 元素。在這種情況下,react 提供瞭解決辦法...
DOM 3 DOM核心和DOM2 HTML 2
由於繼承擴充套件的關係,dom中大部分物件會有node物件的屬性和方法,其中包括 dom2核心中規定的每種nodetype預期的nodena...