虛擬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 虛擬 DOM 和 DOM diff
乙個能代表dom樹的物件,通常含有標籤名 標籤上的屬性 事件監聽和子元素及其它屬性。虛擬dom在vue和react中的示例 const rnode classname red 標籤上的屬性 onclick 事件 ref null,type div 標籤名 or 元件名 const vnode 事件 ...
虛擬DOM和Diff演算法
虛擬dom其實就是在真實dom之前加了一層js物件生成的dom 用js物件模擬dom 把這個虛擬dom物件轉為真實的dom插入到頁面中 如果有事件修改了虛擬dom,比較兩個虛擬dom樹的差異,得到差異物件 補丁 把差異物件應用到正則的dom樹上 比較同級的節點 同一父節點的子節點 當發現節點已經不存...
虛擬DOM和diff演算法
虛擬dom virtual dom 也就是我們常說的虛擬節點,它是通過js的object物件模擬dom中的節點,然後再通過特定的render方法將其渲染成真實的dom的節點。為什麼要使用虛擬dom呢,因為操作真實dom的耗費的效能代價太高,頻繁的操作dom,會大量的造成頁面的重繪和回流,出於效能優化...