概述
VueJS的虚拟DOM是基于开源Snabbdom的。
使用虚拟DOM的好处
前端发展很多年,直到出现了虚拟DOM,才可以从操作DOM解脱出来。
JQuery的出现,简化了操作DOM的过程,但是还是摆脱不了操作DOM。
而虚拟DOM的目的是,使用虚拟节点代替真实节点,所有操作都发生在虚拟节点,然后通过diff算法对比新旧两棵虚拟DOM,计算出更新真实DOM的最少操作,由框架代替用户执行这些操作,所以用户可以把大量的精力放在业务逻辑上。
VNode
在Vue里,使用VNode表示一个虚拟节点,它个结构如下:
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
}
}
解释属性
tag: 当前节点的标签名 data: 当前节点对应的对象,包含了具体的一些数据信息,是一个VNodeData类型,可以参考VNodeData类型中的数据信息 children: 当前节点的子节点,是一个数组 text: 当前节点的文本 elm: 当前虚拟节点对应的真实dom节点 ns: 当前节点的名字空间 context: 当前节点的编译作用域 functionalContext: 函数化组件作用域 key: 节点的key属性,被当作节点的标志,用以优化 componentOptions: 组件的option选项 componentInstance: 当前节点对应的组件的实例 parent: 当前节点的父节点 raw: 简而言之就是是否为原生HTML或只是普通文本,innerHTML的时候为true,textContent的时候为false isStatic: 是否为静态节点 isRootInsert: 是否作为跟节点插入 isComment: 是否为注释节点 isCloned: 是否为克隆节点 isOnce: 是否有v-once指令
VNode类别
在Vue里,VNode分两种类别:
- 普通VNode
- 组件VNode
它们的区别是普通VNode有children属性,而组件VNode的children属性为undefined。