前端vue自学总结Week03——虚拟Dom篇
虚拟Dom是用JS来描述一个真实的DOM节点,在vue中,有个VNode类,就是用VNode类实例化出不同类型的DOM虚拟节点
Vnode类型(6)种
注释节点:text(注释信息)+ is***ment(是否注释节点)(可被创建且插入到Dom中)
文本节点:text(注释信息)(可被创建且插入到Dom中)
元素节点:每个元素都包含(可被创建且插入到Dom中)
组件节点:元素节点+ ***ponentOptionns(组件option选项) + ***ponentInstance(组件节点对应的Vue实例)
函数式节点:组件节点+fnOptions(组件的option选项)+ fnContext(函数式组件对应Vue实例)
克隆节点:每个节点都复制一份 + isClone(是否克隆节点,值为true)
虚拟Dom节点如何更新?
自述总结:通过VNode来更新视图,如何更新呢,
首先在视图渲染之前,把已经写好的template模版编译成VNode缓存下来,
当数据发生变化后,把变化后的生成的VNode与前一次在缓存里面的进行比较,
找出有差异点,差异VNode对应的真实Dom节点就是需要重新渲染的节点位置,
根据差异VNode创建出真实Dom节点再插入到视图中,完成视图更新。
Dom-Diff:对比两份新旧VNode,并找出差异的过程就是所谓的Dom-Diff
DOM-Diff,又称之为patch(补丁)过程,
原理是:在新VNode上,对比旧VNode,
如果新VNode有节点而旧的VNode上没有,就在旧VNode上加上,(创建节点)
如果新VNode上没有,而旧VNoed上有,就在旧VNode上删除,(删除节点)
如果新VNode上有,旧VNode上也有,那么更新旧VNode,保持和新的一致。(更新节点)
关于DOM-Diff更新子节点:
新VNode上子节点即为newChildren,旧VNode上子节点即为oldChildren
创建:每次创建新节点,都放在未处理节点之前
删除:遍历完newChildren,oldChildren还有未处理的节点,删除未处理节点。
更新:newChildren找到了oldChildren中与之对应的节点,并且所处位置也相同,则更新oldVNode节点使之相同
移动:每次移动节点的位置,都放在未处理节点之前
优化更新子节点
例如新的newChildren=[‘新子节点1’, ‘新子节点2’,‘新子节点3’,‘新子节点4’]; oldChildren=[‘旧子节点1’,‘旧子节点2’,‘旧子节点3’,‘旧子节点4’];
优化更新方法:
1、先拿出newChildren中所有未处理节点的第一个子节点(新子节点1)和oldChildren中所有未处理节点的第一个子节点(旧子节点1)进行比较,如果相同,则直接进行更新,如果不同,则进行下一步
2、再拿出newChildren中所有未处理节点的最后一个子节点(新子节点4)和oldChildren中所有未处理节点的最后一个子节点(旧子节点4)进行比较,如果相同,则直接进行更新,如果不同,则进行下一步
3、再拿出newChildren中所有未处理节点的最后一个子节点(新子节点4)和oldChidren中所有未处理节点的第一个子节点(旧子节点1)进行比较,如果相同,则直接进行更新,如果不同,则进行下一步
4、再拿出newChildren中所有未处理节点的第一个子节点(新子节点1)和oldChildren中所有未处理节点的最后一个节点(旧子节点4)进行比较,如果相同,则直接进行更新,如果不同,则进行下一步
5、上午步骤都没有匹配上,开始逐层循环,循环newChildren数组,拿’新子节点1’分别和 旧子节点1,2,3,4进行对比,如果相同则更新,再拿新子节点2’分别和旧子节点1,2,3,4进行更新…如此循环直到更新所有节点
设置newStartIdx,newEndIdx,oldStartIdx,oldEndIdx,这四个变量,分别对应newChildren中开始位置下标,结束位置下标,oldChildren中开始位置下标,结束位置下标;
源码:
当oldStartIdx大于oldEndIdx时,表示oldChildren比newChildren先循环完,表示剩余的newChildren中的节点都是需要新增的,直接把newStartIdx到newEndIdx之间所有的节点插入到Dom中,
当newStartIdx大于newEndIdx时,表示newChildren比oldChildren先循环完,表示oldChildren中所有剩余的节点都是需要删除的,把oldStartIdx到oldEndIdx中所有的节点都删除掉。