1.基本的Diff算法实现了虚拟DOM的最小更新。这句话虽然简短,却涉及到两个核心要素:虚拟DOM和最小更新。1、虚拟DOM虚拟DOM是指将真实的DOM树构造成js对象的形式,从而解决浏览器操作真实DOM的性能问题。例如:如下DOM和虚拟DOM的映射关系2.最小更新Diff的目的是找到新旧虚拟DOM之间的最小更新部分,从而更新这部分对应的DOM。2、整个过程Diff算法真的很美,整个过程如下图所示:首先比较新旧节点是否是同一个节点(通过比较sel(选择器)和key(唯一标识符)是否相同)valuesarethesame),no同一个节点被暴力删除(注意:先在旧节点的基础上插入新节点,再删除旧节点)。如果是同一个节点,还需要进一步比较才完全一样。不把新节点的内容处理成文本,直接替换。新节点有子节点。这时候需要仔细考虑一下:如果旧节点没有子元素,那么直接清空旧节点,插入新节点的子元素即可;如果老节点有子元素,需要按照上面的更新策略来做(记住更新策略,可以吹几年,666666)。3、实战中,我们只讲假手,下面直接输出diff算法的核心内容。3.1patch函数Diff算法的入口函数主要判断新旧节点是否为同一个节点,然后进行不同的逻辑处理。exportdefaultfunctionpatch(oldVnode,newVnode){//判断传入的第一个参数是DOM节点还是虚拟节点if(oldVnode.sel===''||oldVnode.sel===undefined){//传入第一个参数为DOM节点,此时应该封装为虚拟节点oldVnode=vnode(oldVnode.tagName.toLowerCase(),{},[],undefined,oldVnode);}//判断oldVnode和newVnode是否为samenodeif(oldVnode.key===newVnode.key&&oldVnode.sel===newVnode.sel){//是同一个节点,然后进行细化比较patchVnode(oldVnode,newVnode);}else{//不是同一个节点,暴力插入新的,删除旧的letnewVnodeElm=createElement(newVnode);//在旧节点之前插入新节点if(oldVnode.elm.parentNode&&newVnodeElm){oldVnode.elm.parentNode.insertBefore(newVnodeElm,oldVnode.elm);}//删除旧节点oldVnode.elm.parentNode.removeChild(oldVnode.elm);}}3.2patchVnode函数该函数主要负责细粒度比较,根据哪个分支判断ng到上面流程图中的逻辑,从而采用不同的处理逻辑。(思路清晰,算法太棒了)exportdefaultfunctionpatchVnode(oldVnode,newVnode){//判断新旧vnode是否是同一个对象if(oldVnode===newVnode){return;}//判断vnode是否是同一个对象有文本属性newVnode.text!==oldVnode.text){oldVnode.elm.innerText=newVnode.text;}}else{//新vnode没有text属性,但是childrenconsole.log('新vnode没有text属性');//判断老的是否有孩子if(oldVnode.children!==undefined&&oldVnode.children.length>0){//老的有孩子,新的也有孩子updateChildren(oldVnode.elm,oldVnode.children,newVnode.children);}else{//旧的没有孩子,新的有孩子//清除旧节点的内容oldVnode.elm.innerHTML='';//遍历新的子节点vnode,创建DOM,上树for(leti=0;i
