虚拟DOM和真实DOM互相转换

1,965 阅读1分钟

基于Vue的虚拟Dom实现 手动实现虚拟Dom和真实Dom互相转换

1.真实Dom生成虚拟Dom
class Vnode {
  constructor(tag, data, value, type) {
    this.tag = tag && tag.toLowerCase()
    this.data = data
    this.value = value
    this.type = type
    this.children = []
  }
  appendChild(vNode) {
    this.children.push(vNode)
  }
}

// 遍历节点生成虚拟Dom 
function createVnode(node) {
  const nodeType = node.nodeType
  let _vnode = null
  if (nodeType === 1) {
    const tagName = node.nodeName //获取标签类型
    const attrList = node.attributes; //获取标签所有的标签属性
    const attrData = {}  //存放标签属性 
    for (let i = 0; i < attrList.length; i++) {
      attrData[attrList[i].nodeName] = attrList[i].nodeValue
    }
    _vnode = new Vnode(tagName, attrData, undefined, nodeType) // tag,data,value,type
    // 处理子元素
    const childNodes = node.childNodes
    for (let i = 0; i < childNodes.length; i++) {
      _vnode.appendChild(createVnode(childNodes[i]))
    }
  } else if (nodeType === 3) {
    // 文本节点
    _vnode = new Vnode(undefined, undefined, node.nodeValue, nodeType)
  }
  return _vnode
}
2.虚拟Dom生成转为真实Dom
function getRealNode(vnode) {
  // 创建节点
  const { tag, data, value, type, children } = vnode
  let _node = null
  // 判断当前节点是文本节点还是标签节点
  if (type === 1) {
    _node = document.createElement(tag) //创建节点
    for (let key in data) {
      // 设置节点属性
      _node.setAttribute(key, data[key])
    }
    // 追加子节点
    for (let i = 0; i < children.length; i++) {
      // 设置节点属性
      _node.appendChild(getRealNode(children[i]))
    }
  } else if (type === 3) {
    _node = document.createTextNode(value)
  }
  return _node
}