携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第31天,点击查看活动详情
在上文中,我们推定当渲染一个null或者空元素的时候,表示卸载,除了这两种情况,则会把vnode执行patch操作.patch翻译一下叫补丁,作为动词就是打补丁。其实,我觉得所谓补丁就是对新旧vnode进行对比,对比的时候,我们需要区分vnode的类型。
比如说,我们模板里有一个简单的v-if
<template>
<p v-if="a">213</p>
<input v-else />
</template>
假设这时候,a变化了,由true变成了false,我们就大概有这样一个函数调用
const oldNode = {type:'p',children:'123'}
const newNode = {type:'input'}
patch(oldNode,newNode,container)
在这种情况下,再次对比二者的不同是没有必要的,这是两种完全不同的Node,我们需要做的就是卸载旧的,渲染新的。
因此,我们在patch中就需要先判断类型
const patch = (oldNode,newNode,container)=>{
if(oldNode.type!==newNode.type){
unmount(oldNode)
oldNode = null
}
/* 省略其他逻辑 */
}
卸载完成之后,相当于旧Node已经不存在了,我们将他置为null,这样才能不影响后续逻辑。书中讲到这里就算完了,但是实际上,虚拟node很少只是一个简单标签,大部分时候,我们对比的都应该是组件.
比如,ElINput指的是elementUI里input组件,如果我们直接通过===去对比,有可能是相等的,但是这不一定是同一个组件,我可能v-model变化了,或者别的props变化了,但是都是指向的同一个组件的对象。
const oldNode = {type:ElINput}
const newNode = {type:ElINput}
因此,我觉得这里区分vnode的类型,应该是一个递归的对比方法,而不是简单的对比type的值。或者说,当type是字符串的时候,可以进行简单比较,当type类型是对象的时候,需要进行递归比较,对比全部props、attrs
这时候,我就觉得我把属性扁平化会方便很多了,减少很多递归。