實現(xiàn) Virtual DOM 下的一個 VNode 節(jié)點
什么是VNode
我們知道撤摸,render function 會被轉(zhuǎn)化成 VNode 節(jié)點惭等。Virtual DOM 其實就是一棵以 JavaScript 對象(VNode 節(jié)點)作為基礎(chǔ)的樹,用對象屬性來描述節(jié)點蛛砰,實際上它只是一層對真實 DOM 的抽象罐栈。最終可以通過一系列操作使這棵樹映射到真實環(huán)境上。由于 Virtual DOM 是以 JavaScript 對象為基礎(chǔ)而不依賴真實平臺環(huán)境泥畅,所以使它具有了跨平臺的能力荠诬,比如說瀏覽器平臺、Weex位仁、Node 等柑贞。
實現(xiàn)一個VNode
VNode 歸根結(jié)底就是一個 JavaScript 對象,只要這個類的一些屬性可以正確直觀地描述清楚當(dāng)前節(jié)點的信息即可聂抢。我們來實現(xiàn)一個簡單的 VNode
類钧嘶,加入一些基本屬性,為了便于理解琳疏,我們先不考慮復(fù)雜的情況有决。
class VNode {
constructor (tag, data, children, text, elm) {
/*當(dāng)前節(jié)點的標(biāo)簽名*/
this.tag = tag;
/*當(dāng)前節(jié)點的一些數(shù)據(jù)信息闸拿,比如props、attrs等數(shù)據(jù)*/
this.data = data;
/*當(dāng)前節(jié)點的子節(jié)點书幕,是一個數(shù)組*/
this.children = children;
/*當(dāng)前節(jié)點的文本*/
this.text = text;
/*當(dāng)前虛擬節(jié)點對應(yīng)的真實dom節(jié)點*/
this.elm = elm;
}
}
比如我目前有這么一個 Vue 組件新荤。
<template>
<span class="demo" v-show="isShow">
This is a span.
</span>
</template>
用 JavaScript 代碼形式就是這樣的。
function render () {
return new VNode(
'span',
{
/* 指令集合數(shù)組 */
directives: [
{
/* v-show指令 */
rawName: 'v-show',
expression: 'isShow',
name: 'show',
value: true
}
],
/* 靜態(tài)class */
staticClass: 'demo'
},
[ new VNode(undefined, undefined, undefined, 'This is a span.') ]
);
}
看看轉(zhuǎn)換成 VNode 以后的情況台汇。
{
tag: 'span',
data: {
/* 指令集合數(shù)組 */
directives: [
{
/* v-show指令 */
rawName: 'v-show',
expression: 'isShow',
name: 'show',
value: true
}
],
/* 靜態(tài)class */
staticClass: 'demo'
},
text: undefined,
children: [
/* 子節(jié)點是一個文本VNode節(jié)點 */
{
tag: undefined,
data: undefined,
text: 'This is a span.',
children: undefined
}
]
}
然后我們可以將 VNode 進一步封裝一下苛骨,可以實現(xiàn)一些產(chǎn)生常用 VNode 的方法。
- 創(chuàng)建一個空節(jié)點
function createEmptyVNode () {
const node = new VNode();
node.text = '';
return node;
}
- 創(chuàng)建一個文本節(jié)點
function createTextVNode (val) {
return new VNode(undefined, undefined, undefined, String(val));
}
- 克隆一個 VNode 節(jié)點
function cloneVNode (node) {
const cloneVnode = new VNode(
node.tag,
node.data,
node.children,
node.text,
node.elm
);
return cloneVnode;
}
總的來說苟呐,VNode 就是一個 JavaScript 對象痒芝,用 JavaScript 對象的屬性來描述當(dāng)前節(jié)點的一些狀態(tài),用 VNode 節(jié)點的形式來模擬一棵 Virtual DOM 樹牵素。
注:本節(jié)代碼參考《實現(xiàn) Virtual DOM 下的一個 VNode 節(jié)點》严衬。