vm.$parent.$el = vm.$el
}
}
在这个方法当中最为关键的就是vm.__patch__方法,这也是整个virtaul-dom当中最为核心的方法,主要完成了prevVnode和vnode的diff过程并根据需要操作的vdom节点打patch,最后生成新的真实dom节点并完成视图的更新工作。
接下来就让我们看下vm.__patch__里面到底发生了什么:
function patch (oldVnode, vnode, hydrating, removeOnly, parentElm, refElm) {
// 当oldVnode不存在时
if (isUndef(oldVnode)) {
// 创建新的节点
createElm(vnode, insertedVnodeQueue, parentElm, refElm)
} else {
const isRealElement = isDef(oldVnode.nodeType)
if (!isRealElement && sameVnode(oldVnode, vnode)) {
// patch existing root node
// 对oldVnode和vnode进行diff,并对oldVnode打patch
patchVnode(oldVnode, vnode, insertedVnodeQueue, removeOnly)
}
}
}
在对oldVnode和vnode类型判断中有个sameVnode方法,这个方法决定了是否需要对oldVnode和vnode进行diff及patch的过程。
function sameVnode (a, b) {
return (
a.key === b.key &&
a.tag === b.tag &&
a.isComment === b.isComment &&
isDef(a.data) === isDef(b.data) &&
sameInputType(a, b)
)
}
sameVnode会对传入的2个vnode进行基本属性的比较,只有当基本属性相同的情况下才认为这个2个vnode只是局部发生了更新,然后才会对这2个vnode进行diff,如果2个vnode的基本属性存在不一致的情况,那么就会直接跳过diff的过程,进而依据vnode新建一个真实的dom,同时删除老的dom节点。
vnode基本属性的定义可以参见源码:src/vdom/vnode.js里面对于vnode的定义。
constructor (
tag?: string,
data?: VNodeData, // 关于这个节点的data值,包括attrs,style,hook等
children?: ?Array<VNode>, // 子vdom节点
text?: string, // 文本内容
elm?: Node, // 真实的dom节点
context?: Component, // 创建这个vdom的上下文
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.










