DIFF 算法,简易版code实现

54 阅读1分钟
// 定义一个函数,用于比较两个虚拟DOM树的差异
function diff(oldTree, newTree) {
  const patches = {};
   // 递归比较节点
  walk(oldTree, newTree, 0, patches);
   return patches;
}
 // 递归遍历节点,比较差异
function walk(oldNode, newNode, index, patches) {
  const currentPatches = [];
   // 节点被移除
  if (newNode === null) {
    // ...
    // 在patches对象中记录节点被移除的操作
    currentPatches.push({ type: 'REMOVE', index });
  }
  // 节点类型不同,直接替换
  else if (typeof oldNode !== typeof newNode || oldNode.type !== newNode.type) {
    // ...
    // 在patches对象中记录节点替换的操作
    currentPatches.push({ type: 'REPLACE', node: newNode });
  }
  // 节点类型相同,但属性不同,更新属性
  else if (oldNode.type === newNode.type) {
    // ...
    // 在patches对象中记录节点属性更新的操作
    currentPatches.push({ type: 'UPDATE', props: diffProps(oldNode.props, newNode.props) });
     // 递归比较子节点
    diffChildren(oldNode.children, newNode.children, patches);
  }
   // 在patches对象中记录当前节点的差异
  if (currentPatches.length) {
    patches[index] = currentPatches;
  }
}
 // 比较节点属性的差异
function diffProps(oldProps, newProps) {
  const propsPatches = {};
   // 检查新属性中被删除或更新的属性
  for (const key in oldProps) {
    if (oldProps[key] !== newProps[key]) {
      propsPatches[key] = newProps[key];
    }
  }
   // 检查新属性中新增的属性
  for (const key in newProps) {
    if (!oldProps.hasOwnProperty(key)) {
      propsPatches[key] = newProps[key];
    }
  }
   return propsPatches;
}
 // 比较子节点的差异
function diffChildren(oldChildren, newChildren, patches) {
  // ...
  // 递归遍历子节点,比较差异
}
 // 示例使用
const oldTree = {
  type: 'div',
  props: { className: 'container' },
  children: [
    { type: 'h1', props: {}, children: ['Hello'] },
    { type: 'p', props: {}, children: ['World'] }
  ]
};
 const newTree = {
  type: 'div',
  props: { className: 'container' },
  children: [
    { type: 'h1', props: {}, children: ['Hello'] },
    { type: 'p', props: { style: 'color: red' }, children: ['World'] }
  ]
};
 const patches = diff(oldTree, newTree);
console.log(patches);