借鉴https://blog.csdn.net/chenzhizhuo/article/details/101291652心得❤️
思路关键词:
vm._update方法
Vue.prototype._update = function(vnode) {
... 首次渲染
vm.$el = vm.__patch__(vm.$el, vnode) // 覆盖原来的vm.$el
...
}
函数作用/目的👆:将VNode 转为真实的Dom
执行时机(2个):首次渲染时、更新页面时
a:首次渲染时:就是new Vue()实例的首次render->patch 本文关键:
组件页面是否重新render取决于patch方法:【 https://www.jb51.net/article/183459.htm
1⃣️是什么?
是个函数方法,接收2个形参:新、旧VNode, 遍历比较前后2个VNode的所有属性,是否发生了变化/没发生变化。
遍历前后的VNode时->if判断属性内容如下:
- key相同
- 标签类型相同
- 注释节点标识相同,都是注释节点,或者都不是注释节点
- data的值状态相同,或者都有值,或者都没值
- 以上可判定为相同节点
结论:如果属性都相同,代表不用重新render。有不同,则需要重新render。
功能类似:shouldComponentUpdate(){}、 PureComponent
2⃣️patch判断流程如下 :
a) 如果新节点为空,此时旧节点存在(组件销毁时),调用旧节点destroy生命周期函数
b) 如果旧节点为空,根据新节点创建DOM
c) 其他(如果新旧节点都存在)
- a) 旧节点不是DOM(组件节点),且新旧节点相同
- 执行patchVnode
- b) 旧节点是DOM元素或者两个节点不相同
- 创建新节点DOM,销毁旧节点以及DOM。
3⃣️干啥用:组件页面渲染时,将render返回的新vnode(新节点)和组件实例保存的vnode(旧节点)作为参数,调用patch方法,更新DOM。
4⃣️适用场景:
.........
4⃣️代码实现?
function sameVnode (a, b) {// 判断两个VNode节点是否是同一个节点
return (
a.key === b.key && // key相同
(
a.tag === b.tag && // tag相同
a.isComment === b.isComment && // 注释节点标识相同
isDef(a.data) === isDef(b.data) && // data值状态相同
sameInputType(a, b) // input的type相同
)
)
}
Vue.prototype.__patch__ = createPatchFunction({ nodeOps, modules })
】
b: 更新页面时:经props和数据的更新,生成前后两份虚拟Dom(VNode)->diff算法比较出最小差异。
2: 真实DOM的生成
2.1: 注意⚠️:无论VNode 是什么类型的节点, 只有三种类型的节点会被创建并插入到Dom中: 元素节点,注释节点, 和文本节点。
2.2: createElm 方法开始生成真实的Dom
2.3: 虚拟DOM -> 真实Dom 的方式:分为元素节点和组件2种
2.3.1: 元素节点生成Dom代码实例👇:
<div>
<h1>title h1</h1>
<h2>title h2</h2>
<h3>title h3</h3>
</div>
{ // 元素节点VNode
tag: 'div',
children: [{
tag: 'h1',
children: [
{text: 'title h1'}
]
}, {
tag: 'h2',
children: [
{text: 'title h2'}
]
}, {
tag: 'h3',
children: [
{text: 'title h3'}
]
}
]
}
创建元素节点流程图-复用👇:
Vue父子组件的执行顺序:
个人记忆口诀:【父1、父2、父3 】--->【子1、子2、子3】--->【子4、父4】
parent beforeCreate
parent created
parent beforeMounte
child beforeCreate
child created
child beforeMounte
child mounted
parent mounted