(一)什么是虚拟节点
在vue中,采用虚拟节点进行dom的模拟,以减少真实dom的创建更新达到优化的目的
(二)diff是怎么比较的
vue 比较节点的入口是patch 函数(old,vnode,hyd,removeonly), 在patch的过程中会判断节点是否需要更新在patchVnode中决定,patchVnode中对各种节点的情况做出不同的处理,其中的主要对比逻辑在updateChildre中 即:
patch(old,vnode){
if(patchable){
patchVnode(oldVnode,newVnode);
}
}
patchVnode(oldVnode,newVnode){
// 省略各种不需要更新子节点的情况
updateChildren(oldVnode.children,newVnode.children)
// 这里vNode中children节点是一个数组,updateChildren中采用双指针的方法进行数组的遍历。
}
patchVode过程:
patchVode 入参:新旧节点,插入到新节点的队列
如果新旧节点相等=>返回
新旧节点为静态节点/once节点。返回,不进行patch
新节点不为text=>新旧节点都有子节点=>updateChildren
新节点有子节点,addnodes(增加新节点中的子节点);(此之前会检查key,有重复则报错提醒)
旧节点有子节点: removeNodes(删除旧节点中的子节点);
新节点为text=>新旧节点text不同则做更新旧节点
updateChildren过程:
两个新旧节点的数组:伪代码
if(oldStart == newStart){
oldStart++;
newStart++;
}
if(oldEnd == newOld){
oldEnd--;
newOld--;
}
if(oldStart == newEnd){
patchVonde(oldStart,newEnd);
insert newEnd before oldStart
}
if(oldEnd == newStart){
patchVonde(oldEnd,newStart);
insert newStart before oldEnd
}
// key 的作用 有key的时候会复用oldNode =>但是会增加一次patch 的过程
// 没有key => 直接新建节点-》dom操作
if(newStart的key在旧节点的key中可以找到){
// 要插入的节点=旧节点中相同key的节点
if(要插入的节点和newStart是相同节点){
patchVnode(要插入的节点、newStart);
在oldStart前插入(要插入的节点)
}
}else{
创建一个新的节点并插入到oldStart前
}
stateDiagram-v2
[*]-->新节点不存在
[*]-->新节点存在
新节点不存在 --> 旧节点存在
旧节点存在 --> 销毁旧节点(destroy)
新节点存在 --> 旧节点不存在
旧节点不存在 --> 新增节点
新节点存在 --> 旧节点存在且新旧都为vnode
旧节点存在且新旧都为vnode --> patchVnode
新节点存在 --> 旧节点为真实dom
旧节点为真实dom --> 同事