虚拟DOM和diff算法(三) patch方法(基础版本)

176 阅读2分钟
/*
* 实现节点对比,旧节点如果是dom 则调用vnode 包装成-虚拟dom节点
* 判断新旧节点是否一致,key和node名一致 则认为是同一节点?
* 如果新旧节点不一致 暴力删除
*/
import vnode from "./vnode.js"
import createElement from "./createElement.js"

export default function (oldVnode, newVnode) {
  // 判断旧节点是否为dom节点,还是虚拟节点
  if (oldVnode.sel == undefined || oldVnode.sel == '') {
  // 传入第一个参数是DOM节点,此时要包装成虚拟节点
    oldVnode = vnode(oldVnode.tagName.toLowerCase(), {}, [], undefined, oldVnode)
  }
  // 判断新旧节点是否一致
  if (oldVnode.key === newVnode.key && oldVnode.sel === newVnode.sel) {
      console.log('同一个节点')
  } else {
    // console.log('不是同一个几点,需要删除,重新插入节点')
    // 保持createElement 函数作用单一简单,所以插入节点不在里面做,将标杆移除,到外部
    const newVnodeDom = createElement(newVnode)
    if (oldVnode.elm.parentElement && newVnodeDom) {
      // appendchild 是没有标杆的 是无序的 insertbefore是有标杆的
      // 最后一层用insertBefore追加
      oldVnode.elm.parentElement.insertBefore(newVnodeDom, oldVnode.elm)
    }
    // 删除老节点
    oldVnode.elm.parentElement.removeChild(oldVnode.elm)
  }
}
/*
 * 保持createElement 函数作用单一简单,所以插入节点不在里面做
 * 将标杆移除,到外部
 * 创建dom节点,内部有文本,不是空 并且children不是空 或者 不是0
 * 他内部具有子节点,需要递归创建节点
 * 
 */
export default function createElement(vnode) {
  // console.log('目的把虚拟节点', vnode, '插入到标杆');
  // 创建dom节点,目前此简单还是孤单节点
  let domNode = document.createElement(vnode.sel);
  // 有子节点还是有文本?
  // 内部有文本,不是空 并且children不是空 或者 不是0
  if (vnode.text != '' && (vnode.children == undefined || vnode.children.children == 0)) {
    // 处理内部文字
    domNode.innerText = vnode.text;
  } else if (Array.isArray(vnode.children) && vnode.children.length > 0){
     // 他内部具有子节点,需要递归创建节点
    let i = 0
    while (i < vnode.children.length) {
      // 得到当前这个children
      const Chi = vnode.children[i]
      console.log(Chi)
      // 创建出它的DOM,一旦调用createElement意味着:创建了DOM,并将它的elm属性指向了创建出的DOM,但依旧没有上树,是个孤儿节点
      const chDOM = createElement(Chi)
      // 上树
      domNode.appendChild(chDOM)
      i++
    }
  }
  // 补充elm属性
  vnode.elm = domNode
  // 返回elm用于递归,纯dom对象
  return vnode.elm
}
``
![8ef70ee838ad77b6dd83751b5092d5d6.png](en-resource://database/3528:0)