-
Virtual DOM 這個概念相信大多數(shù)的開發(fā)人員都不會陌生饺谬,它產(chǎn)生的前提就是操作瀏覽器中的 DOM 是很 ·昂貴· 的,為了更直觀的看到谣拣,我把一個簡單的 div 元素的屬性打印出來:
demo.png 上面可以看到募寨,真正的 DOM 元素是非常龐大的,當(dāng)我們頻繁的去做 DOM 操作森缠,會產(chǎn)生一定的性能問題拔鹰。
而 Virtual DOM 就是一個用原生的 JS 對象去描述一個 DOM 節(jié)點,所以它比創(chuàng)建一個 DOM 的代價要小很多贵涵。在 Vue.js 中列肢,Virtual DOM 就是用 VNode 這個一個 class 去描述,定義在 src/core/vdom/vnode.js 中:
export default class VNode {
tag: string | void;
data: VNodeData | void;
children: ?Array<VNode>;
text: string | void;
elm: Node | void;
ns: string | void;
context: Component | void; // rendered in this component's scope
key: string | number | void;
componentOptions: VNodeComponentOptions | void;
componentInstance: Component | void; // component instance
parent: VNode | void; // component placeholder node
// strictly internal
raw: boolean; // contains raw HTML? (server only)
isStatic: boolean; // hoisted static node
isRootInsert: boolean; // necessary for enter transition check
isComment: boolean; // empty comment placeholder?
isCloned: boolean; // is a cloned node?
isOnce: boolean; // is a v-once node?
asyncFactory: Function | void; // async component factory function
asyncMeta: Object | void;
isAsyncPlaceholder: boolean;
ssrContext: Object | void;
fnContext: Component | void; // real context vm for functional nodes
fnOptions: ?ComponentOptions; // for SSR caching
fnScopeId: ?string; // functional scope id support
constructor (
tag?: string,
data?: VNodeData,
children?: ?Array<VNode>,
text?: string,
elm?: Node,
context?: Component,
componentOptions?: VNodeComponentOptions,
asyncFactory?: Function
) {
this.tag = tag
this.data = data
this.children = children
this.text = text
this.elm = elm
this.ns = undefined
this.context = context
this.fnContext = undefined
this.fnOptions = undefined
this.fnScopeId = undefined
this.key = data && data.key
this.componentOptions = componentOptions
this.componentInstance = undefined
this.parent = undefined
this.raw = false
this.isStatic = false
this.isRootInsert = true
this.isComment = false
this.isCloned = false
this.isOnce = false
this.asyncFactory = asyncFactory
this.asyncMeta = undefined
this.isAsyncPlaceholder = false
}
// DEPRECATED: alias for componentInstance for backwards compat.
/* istanbul ignore next */
get child (): Component | void {
return this.componentInstance
}
}
- 上面可以看到 Vue.js 中的 Virtual DOM 的定義還是略微復(fù)雜一些宾茂,因為它這里包含了很多 Vue 的特性瓷马。實際上 Vue 中 Virtual DOM 是借鑒了一個開源庫 snabbdom 的實現(xiàn),然后加入了一些 Vue 特色的東西跨晴。還是建議去看一下這個開源庫决采,而我后面頁面寫一篇關(guān)于這個開源庫的文章。
其實 VNode 是對真實 DOM 的一種抽象描述坟奥,它的核心定義無非就是幾個關(guān)鍵屬性树瞭,例如: 標(biāo)簽名、數(shù)據(jù)爱谁、子節(jié)點晒喷、鍵值等。其它屬性都是用來擴展 VNode 的靈活性以及實現(xiàn)一些特殊的 feature 的访敌。由于 VNode 知識用來映射到真實 DOM 的渲染凉敲,不需要包含操作 DOM 的方法,因此它是非常輕量和簡單的寺旺。
Virtual DOM 除了它的數(shù)據(jù)結(jié)構(gòu)的定義爷抓,映射到真實的 DOM 實際上要經(jīng)歷 VNode 的 create、diff阻塑、patch 等過程蓝撇。