moy-dom
Version:
A flexiable Virtual DOM library for building modern web interface.
78 lines (70 loc) • 2.52 kB
JavaScript
import listDiff from '../listDiff/index'
import diffProps from './diffProps'
/**
* [diffChildren diff two children list]
* @param {[Array]} newChildren [the Element Array for old children]
* @param {[Array]} oldChildren [the Element Array for new children]
* @param {[Number]} index [current node index]
* @param {[Object]} patches [patches]
* @param {[Object]} currentPatches [current node patches]
* @return {[undefined]} [undefined]
*/
const diffChildren = function(newChildren, oldChildren, index, patches, currentPatches){
const { children, changes } = listDiff(newChildren, oldChildren)
if(changes.length){
currentPatches.push({ // remove, move, insert, append node
type: 1,
changes,
})
}
newChildren = children // children -> newChildren for deep compare
let leftNode = null, currentNodeIndex = index
for(let [index, oldChild] of oldChildren.entries()){
const newChild = newChildren[index]
currentNodeIndex += 1 + (leftNode && leftNode.count ?
leftNode.count : 0)
dfsWalk(newChild, oldChild, currentNodeIndex, patches)
leftNode = oldChild
}
}
/**
* [dfsWalk diff two node tree]
* @param {[Element]} newTree [new tree]
* @param {[Element]} oldTree [old tree]
* @param {[Number]} index [current tree node index]
* @param {[Object]} patches [patches]
* @return {[undefined]} [undefined]
*/
export default function dfsWalk(newTree, oldTree, index, patches){
const currentPatches = []
if(newTree === null){
// Real DOM node will be removed when perform reordering, so has no needs to do anthings in here
}else if(Object.prototype.toString.call(newTree) === '[object String]' &&
Object.prototype.toString.call(oldTree) === '[object String]'){
newTree !== oldTree &&
currentPatches.push({
type: 3, // text node
content: newTree,
})
}else if(newTree.tagName === oldTree.tagName &&
newTree.key === oldTree.key){
const propPatches = diffProps(newTree.props, oldTree.props)
if(propPatches){
currentPatches.push({
type: 2, // props changed
props: propPatches,
})
}
if(!newTree.props.ignore){
diffChildren(newTree.children, oldTree.children, index, patches, currentPatches)
}
}else{
currentPatches.push({
type: 0, // not the same node, replace it
node: newTree,
})
}
if(currentPatches.length){
patches[index] = currentPatches
}
}