当前位置: 首页 > Web前端 > vue.js

Vue3的diff算法

时间:2023-03-31 15:53:28 vue.js

1.可能性(常见):1.旧的:abc新的:abcd2。旧的:abc新的:dabc3。旧的:abcd新的:abc4。旧:dabc新:abc5。Old:abcdeifgNew:abecdhfg对应真实的虚拟节点(为了方便理解,文字用字母代替)://vnodeobjectconsta={type:'div',//labelprops:{style:{color:'red'}},//属性children:[],//子元素key:'key1',//keyel:'

',//truedomnode...}2.找到pattern,去掉前后相同的部分//c1表示旧的子节点,c2表示新的子节点constpatchKeyedChildren=(c1,c2)=>{leti=0lete1=c1.length-1lete2=c2.length-1//从前面比较while(i<=e1&&i<=e2){constn1=c1[i]constn2=c2[i]//label和key是否相同//if(n1.type===n2.type&&n1.key===n2.key)if(n1===n2){//继续比较其属性和子节点}else{break}i++}//从后面开始比较while(i<=e1&&i<=e2){constn1=c1[e1]constn2=c2[e2]//标签和键是相同的//if(n1.type===n2.type&&n1.key===n2.key)if(n1===n2){//继续比较它的属性和子部分dot}else{break}e1--e2--}console.log(i,e1,e2)}//调用示例patchKeyedChildren(['a','b','c','d'],['a','b','c'])可以通过这个函数得到:1.Old:abcNew:abcdi=3e1=2e2=32.Old:abcNew:dabci=0e1=-1e2=03。旧的:abcd新的:abci=3e1=3e2=24。旧的:dabc新的:abci=0e1=0e2=-15。旧:abcdeifg新:abecdhfgi=2e1=5e2=5扩展:旧:abc新:abcdefi=3e1=2e2=5旧:abc新:abci=3e1=2e2=2旧:edabcnew:abci=0e1=1e2=-1old:cdenew:ecdhi??=0e1=2e2=3从上面的结果我们可以发现规律:当i大于e1时,只需添加New子节点当i大于e2时,只删除旧的子节点//当i大于e1if(i>e1){if(i<=e2){while(i<=e2){constnextPos=e2+1constanchor=nextPose2){if(i<=e1){while(i<=e1){//删除旧子节点c1[i]//todoi++}}}other,特殊处理//otherlets1=ilets2=i//使用新的子节点作为引用constkeyToNewIndexMap=newMap()for(leti=s2;i<=e2;i++){//节点的key作为唯一值//keyToNewIndexMap.set(c2[i].key,i)keyToNewIndexMap.set(c2[i],i)}//新的总数consttoBePatched=e2-s2+1//在旧的子节点中记录新的子节点IndexinconstnewIndexToOldIndexMap=newArray(toBePatched).fill(0)//遍历旧的子节点for(leti=s1;i<=e1;i++){constoldChild=c1[i]//letnewIndex=keyToNewIndexMap.get(oldChild.key)letnewIndex=keyToNewIndexMap.get(oldChild)//新子节点不存在if(newIndex===undefined){//deleteoldChild//todo}else{newIndexToOldIndexMap[newIndex-s2]=i+1//永远不会等于0,所以0可以表示需要创建//继续比较它的属性和子节点//todo}}console.log(newIndexToOldIndexMap)//需要移动positionfor(leti=toBePatched-1;i>=0;i--){让索引=i+s2让current=c2[index]让anchor=index+1[1,2]让increment=getSequence(newIndexToOldIndexMap)console.log(increment)letj=increment.length-1for(leti=toBePatched-1;i>=0;i--){让index=i+s2让current=c2[index]让anchor=index+1>1//相当于Math.floor((start+end)/2)if(arr[min_arr[middle]]arrI){min_arr[end]=iif(end>0){prev_arr[i]=min_arr[end-1]//前一个索引}}}}//从最后一项向前搜索letresult=[]leti=min_arr.lengthletlast=min_arr[i-1]while(i-->0){result[i]=lastlast=prev_arr[last]}returnresult}//c1代表老子节点,c2代表新子节点constpatchKeyedChildren=(c1,c2)=>{leti=0lete1=c1.length-1lete2=c2.length-1//从前面比较while(i<=e1&&i<=e2){constn1=c1[i]constn2=c2[i]//label和key是否相同//if(n1.type===n2.type&&n1.key===n2.key)if(n1===n2){//继续比较它的属性和子节点}else{break}i++}//从后面比较while(i<=e1&&i<=e2){constn1=c1[e1]constn2=c2[e2]//label和key是否相同//if(n1.type===n2.type&&n1.key===n2.key)if(n1===n2){//继续比较其属性和子节点}else{break}e1--e2--}console.log(i,e1,e2)//当i大于e1if(i>e1){if(i<=e2){while(i<=e2){constnextPos=e2+1constanchor=nextPose2){if(i<=e1){while(i<=e1){//删除子节点c1[i]//todoi++}}}//elseelse{lets1=ilets2=i//使用新的子节点作为引用constkeyToNewIndexMap=newMap()for(leti=s2;i<=e2;i++){//节点的key作为唯一值//keyToNewIndexMap.set(c2[i].key,i)keyToNewIndexMap.set(c2[i],i)}//新的总数consttoBePatched=e2-s2+1//在旧的记录新的子节点子节点中的索引constnewIndexToOldIndexMap=newArray(toBePatched).fill(0)//遍历旧子节点for(leti=s1;i<=e1;i++){constoldChild=c1[i]//letnewIndex=keyToNewIndexMap.get(oldChild.key)letnewIndex=keyToNewIndexMap.get(oldChild)//新子节点不存在if(newIndex===undefined){//deleteoldChild//todo}else{newIndexToOldIndexMap[newIndex-s2]=i+1//永远不会等于0,所以0可以表示需要创建//继续比较它的属性和子节点//todo}}console.log(newIndexToOldIndexMap)//需要moveposition//find获取最长递增子序列对应的索引值,如:[5,3,4,0]->[1,2]letincrement=getSequence(newIndexToOldIndexMap)console.log(increment)letj=increment.length-1对于(设i=toBePatched-1;我>=0;i--){让index=i+s2让current=c2[index]letanchor=index+1
最新推荐
猜你喜欢