概念diff算法的生成主要是直接操作dom,比较浪费性能。dom-diff可以在每次渲染时进行比较。例如,一个列表中有三个元素,过一段时间会生成一条新的数据。如果可以复用的元素直接复用,不操作相同的元素,diff算法的特点是层次比较dom-diff是对虚拟节点进行操作的,虚拟节点的属性很少(tag,data,children,key)realdom,每次操作realdom都会重新创建很多属性,极大的消耗了diff算法实现的性能。我们还了解到diff算法使用旧虚拟节点和新虚拟节点。节点是比较的,那么我们来看看比较规则。那么我们现在使用vue源码中的三个方法生成两个虚拟节点。//compileToFunction解析html生成render函数import{compileToFunction}from'./compiler/index.js';//patch虚拟节点对比//createElm创建真的是domimport{patch,createElm}from'./vdom/patch';//1.创建第一个虚拟节点letvm1=newVue({data:{name:'meng'}});letrender1=compileToFunction('
{{name}}}
')letoldVnode=render1.call(vm1)//2.创建第二个虚拟节点letvm2=newVue({data:{name:'li'}});letrender2=compileToFunction('{{name}}
');letnewVnode=render2.call(vm2);//3.通过第一个虚拟节点进行第一次渲染letel=createElm(oldVnode)document.body.appendChild(el);//4.调用patch方法进行比较操作patch(oldVnode,newVnode);生成后的虚拟节点,如下图所示console.log(oldVnode,newVnode)1.标签比较如果标签不同,就用新的替换旧的if(oldVnode.tag!==vnode.tag){oldVnode.el.parentNode.replaceChild(createElm(vnode),oldVnode.el)}2.标签中的文本比较//如果标签不存在,则为文本如果文本不一致,让新的替换旧的内容同时复用旧标签,只有内容替换节省了创建标签的性能}}3。比较属性//重用标签,并更新属性让el=vnode.el=oldVnode.el;updateProperties(vnode,oldVnode.data);functionupdateProperties(vnode,oldProps={}){让newProps=vnode.data||{};让el=vnode.el;//比较样式letnewStyle=newProps.style||{};让oldStyle=oldProps.style||{};//如果新的属性不存在,直接清除旧的oldProps中的键){if(!newProps[key]){el.removeAttribute(key);}}for(letkeyinnewProps){if(key==='style'){for(letstyleNameinnewProps.style){el.style[styleName]=newProps.style[styleName];}}elseif(key==='class'){el.className=newProps.class;}else{el.setAttribute(key,newProps[key]);}}}4.子元素比较//比较子节点letoldChildren=oldVnode.children||[];让newChildren=vnode.children||[];//新旧都需要比较Childif(oldChildren.length>0&&newChildren.length>0){//老的有儿子,新的不清零}elseif(oldChildren.length>0){el.innerHTML='';//New有孩子}elseif(newChildren.length>0){for(leti=0;i