list-diff的源代码react
在vue或者react内,每个VNode都有一个惟一key来标识,一般是框架自动处理,可是在循环内必须由开发者指定。因此如下解读我就是用这个key来表明list内的对象。git
咱们并不须要真的达到最小的操做,咱们只须要优化一些比较常见的移动状况,牺牲必定DOM操做,让算法时间复杂度达到线性的(O(max(M, N))github
let diff = (oldList, newList) => { let moves = []; // 逻辑处理 return moves; }
由上能够看出,diff函数返回的是将旧数组转换成新数组的步骤
下面我会详细说明中间的逻辑处理步骤算法
oldList = [ A, B, C, D]; newList = [ E ,C, D, B];
var simulateList = []; oldList.forEach((item, index) => { // 此item存在于newList内 if (newList.indexOf(item) !== -1) { simulateList.push(item) } else { moves.push({ type: 'remove', index: index }) } }); // 程序运行结束,此时simulateList 就是oldList与newList的交集,而且是按oldList的顺序进行排序的 // 此时simulateList的值为[ B, C, D] // 此时moves的值为[{type:'remove',index:0}],标识将下标为0的item从oldList内删除,即删除A
newList = [E,C,D,B]; simulateList= [B,C,D]; // i与j分别是newList与simulateList的下标 // newList E 与 simulateList B 比较,E 不等于 B 且 E 不存在于simulateList中,则insert E // 此时i=0;j=0; moves = [ {type:'remove',index:0}, {type:'insert',index:0,item:E} ]; i++; // newList C 与 simulateList B 比较,C 不等于 B 且 simulateList B 的下一个为 C,则remove B // i=1;j=0; moves = [ {type:'remove',index:0}, {type:'insert',index:0,item:E}, {type:'remove',index:1} ] i++; j++; // 4. newList D 与 simulateList D 比较,相等则进入下一步比较 i++; j++; // 5. newList B,此时simulateList 已经比较完了,则 insert B // i=3;j=2; moves = [ {type:'remove',index:0}, {type:'insert',index:0,item:E}, {type:'remove',index:1}, {type:'inser', item: B, index: 3} ]
最终返回的数据如上所示,按照这个步骤,能够将oldList转变为newList,一般状况下对于list的改变主要集中在,删除数据,或者新增数据,将list数据所有打乱的状况极少,因此以上算法基本知足咱们的须要。数组
由上能够看出惟一key的重要性,在用vue或者react写list的时候,务必要使用惟一的固定值做为能够,杜绝用数组下标做为key的写法。框架
第一次写文章,不足之处还请海涵