vue学习篇4之模板解析与虚拟DOM

模板解析
模板:就是html嵌套js代码,js代码以两种形式存在于页面里,指令属性和表达式
模板解析大括号表达式{{}}的基本流程:
1、将el的所有子节点取出,添加到一个新建的文档fragement对象中。
2、对fragement中的所有层次子节点递归进行编译解析处理。
3、通过nodeType判断节点是元素节点还是文本节点
4、如果是元素节点根据正则表达式得到匹配出的表达式字符串。/{{(.+?)}}/g
5、从data中取出表达式对应的属性值
6、将属性值设置为文本节点的textContent
7、将解析后的fragement添加到el中

虚拟DOM
为什么要使用虚拟DOM?
因为提高性能。如果直接在页面当中去操作DOM页面要不断的更新,很消耗性能,使用虚拟DOM所有的操作都在内存里面,只需要虚拟DOM的处理完成了更新到页面上只用更新一次。
虚拟DOM是一个对象
1、怎么将真正的DOM转换为虚拟DOM?

<div id="root">
  <div>hello</div>
</div>

<script>
  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元素,生成虚拟DOM
  function getVNode(node) {
    let nodeType = node.nodeType
    let _vnode = null
    if (nodeType === 1) { //元素
      let nodeName = node.nodeName
      let attrs = node.attributes
      let _attrsObj = {}
      for (let i = 0; i < attrs.length; i++) {  //attrs[i]属性节点  (nodeType===2)
        _attrsObj[attrs[i].nodeName] = attrs[i].nodeValue
      }
      _vnode = new VNode(nodeNamw, _attrsObj, undefined, nodeType)

      //考虑node的子元素
      let childNodes = node.childNodes
      for (let i = 0; i < childNodes .length; i++) {
        _vnode.appendChild (getVNode(childNodes [i]))  //递归
      }
    } else if (nodeType === 3) {
      _vnode = new VNode(undefined, undefined, node.nodeValue, nodeType)
    }
    return _vnode
  }

let root = document.querySelector('#root')
let vroot = getVNode(root)
console.log(vroot) 
</script>

2、怎么将虚拟DOM转换为真正的DOM?

function parseVNode (vnode) {
  //创建真实的DOM
  let type= vnode.type
  let _node = null
  if (type === 3) {
    return document.createTextNode(vnode.value)  //创建文本节点
  } else if (type === 1) {
    _node = document.createElement(vnode.tag)
    //处理属性
    let data = vnode.data
    Object.keys(data).forEach(key => {
      let attrName = key
      let attrValue = data[key]
      _node.setAttribute(attrName ,attrValue)
    })
    //处理子元素
    let children = vnode.children
    children .forEach(subnode => {
      _node.appendChild (parseVNode(subnode ))  //递归转换子元素 (是一个虚拟DOM)
    })
    return _node
  }
}

let dom2 = parseVNode(vroot)
console.log(dom2)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容