Vue.js.2.0以后采用了一个中等粒度的解决方案来来更新视图,即引入虚拟DOM.Watcher实例对应到组件级别.即使一个组件中多个节点使用了某个状态,也只有一个Watcher实例在侦测这一状态.当这个状态发生了变化时,只能通知到组件,然后由组件内部通过对比虚拟DOM来确定哪一个节点需要被重新渲染.这是一个比较折中的方案.
虚拟DOM到视图更新整体运行流程:将模板编译成渲染函数(Render),通过执行渲染函数生成Vnode,将Vnode和OldVnode做对比,最后更新视图.
虚拟 DOM主要做了两件事:
Vnode是什么?
Vnode是虚拟DOM中一个重要的内容,是Vuejs中的一个类,用来实例化不同类型的Vnode实例,这些实例代表了不同类型的DOM元素:
1.注释节点 2.文本节点 3.元素节点 4.组件节点 5.函数节点 6.克隆节点.
简单来讲,Vnode可以理解为节点描述对象,描述了怎样去创建一个真实的DOM节点.不同类型的Vnode只是有效属性不同(无效属性会被默认为undefined或false).定义如下:
constructor (
tag?: string, //节点名称,如p,ul,li,div
data?: VNodeData, // 关于这个节点的data值,包括attrs,style,hook等
children?: ?Array, // 当前节点的子节点
text?: string, // 文本内容
elm?: Node, // 真实的dom节点
context?: Component, // 当前组件的VUE实例
componentOptions?: VNodeComponentOptions
) {
this.tag = tag
this.data = data
this.children = children
this.text = text
this.elm = elm
this.ns = undefined
this.context = context
this.functionalContext = 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
}
// DEPRECATED: alias for componentInstance for backwards compat.
/* istanbul ignore next */
get child (): Component | void {
return this.componentInstance
}
}
比如我定义了一个Vnode,它的数据结构是:
{
tag: 'div'
data: {
id: 'app',
class: 'page-box'
},
children: [
{
tag: 'p',
text: 'this is demo'
}
]
}
那么由它所渲染出来的DOM节点就是:
this is demo
克隆节点 :克隆节点将一个Vnode的属性全都复制到一个新的Vnode中.其作用是优化静态节点以及slot Node(插槽节点).因为静态节点的内容不会改变,所以除了首次渲染时需要执行渲染函数来获取Vnode之外,后续都不需要重新渲染生成,所以直接使用克隆节点进行渲染即可.
// optimized shallow clone
// used for static nodes and slot nodes because they may be reused across
// multiple renders, cloning them avoids errors when DOM manipulations rely
// on their elm reference.
export function cloneVNode (vnode: VNode): VNode {
const cloned = new VNode(
vnode.tag,
vnode.data,
// #7975
// clone children array to avoid mutating original in case of cloning
// a child.
vnode.children && vnode.children.slice(),
vnode.text,
vnode.elm,
vnode.context,
vnode.componentOptions,
vnode.asyncFactory
)
cloned.ns = vnode.ns
cloned.isStatic = vnode.isStatic
cloned.key = vnode.key
cloned.isComment = vnode.isComment
cloned.fnContext = vnode.fnContext
cloned.fnOptions = vnode.fnOptions
cloned.fnScopeId = vnode.fnScopeId
cloned.asyncMeta = vnode.asyncMeta
cloned.isCloned = true
return cloned
}
PS 克隆节点和被克隆节点唯一的区别就是isCloned属性,克隆节点为True,被克隆节点为False.
以上就是关于Vue关于Vnode的主要内容,后续将深入介绍虚拟DOM的实现原理.
本文章仅为本人学习总结,如果有不足还请各位指出!