UNPKG

moy-dom

Version:

A flexiable Virtual DOM library for building modern web interface.

113 lines (100 loc) 3.06 kB
import makeKeyIndexAndFree from './makeKeyIndexAndFree' import remove from './remove' import move from './move' import insert from './insert' import append from './append' /** * [listDiff diff two List] * @param {[Array]} newList [the new List] * @param {[Array]} oldList [the old List] * @return {[Object]} [a children property for deep compare and a changes for two list's diffs] * * @changes's type * 0 -> remove * 1 -> move * 2 -> insert * 3 -> append */ export default function listDiff(newList, oldList){ const { keyIndex: newKeyIndex, free: newFree, } = makeKeyIndexAndFree(newList), // need keyIndex Map for eazy to find key children = [], // the same struct as old list for deep compare changes = [], // the changes newFreeLength = newFree.length let newFreeIndex = 0, hittingItemKeyIndex, oldItemKey // first we get old list same struct children for deep compare for(let oldItem of oldList){ oldItemKey = oldItem.key if(oldItemKey !== undefined){ hittingItemKeyIndex = newKeyIndex.get(oldItemKey) children.push( hittingItemKeyIndex !== undefined ? newList[hittingItemKeyIndex] : null ) }else{ // original place children.push( newFreeIndex < newFreeLength ? newFree[newFreeIndex ++] : null ) } } const simulateList = [...children] // the simulate for list changes let simulateIndex = 0, simulateLength = simulateList.length // remove null items represent not exit items in new list while(simulateIndex < simulateLength){ if(simulateList[simulateIndex] === null){ remove(simulateIndex, simulateList, changes) simulateLength -- }else{ simulateIndex ++ } } simulateIndex = 0 let newIndex = 0, newLength = newList.length, simulateKeyIndex, // may need simulateKeyIndex for deep compare simulateItem, simulateItemKey, newItem, newItemKey // point to point compare while(simulateIndex < simulateLength && newIndex < newLength){ simulateItem = simulateList[simulateIndex] simulateItemKey = simulateItem.key newItem = newList[newIndex] newItemKey = newItem.key // the same node if(newItemKey === simulateItemKey){ simulateIndex ++ newIndex ++ }else{ if(!simulateKeyIndex){ // get simulateKeyIndex simulateKeyIndex = makeKeyIndexAndFree(simulateList).keyIndex } if((hittingItemKeyIndex = simulateKeyIndex.get(newItemKey))){ // find the same key in old list, just move it move(newIndex ++, hittingItemKeyIndex, simulateList, changes) simulateIndex ++ }else{ // otherwise inset a new one insert(newIndex, newItem, simulateList, changes) simulateLength ++ simulateIndex ++ newIndex ++ } } } // rest new list item should be append while(newIndex < newLength){ append(newList[newIndex ++], simulateList, changes) } return { children, changes, } }