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的寫法。框架
第一次寫文章,不足之處還請海涵