vue模板解析、虚拟DOM

看了某站上面的视频,做一个学习记录

compiler.html

代码复制在F12控制台可看见原始DOM、虚拟DOM、以及编译成功的真实DOM

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<script src="./compiler.js"></script>
<body>
  <div id="app" title="66">
     <div class="a1">
       <div class="a2">{{user.name}}</div>
       <div>{{user.age}}</div>
       <div>{{user.ah.yy}}</div>
     </div>
     <div>{{flag}}</div>
     <div>{{age}}</div>
  </div>
   <script>
    // vue数据驱动
      class SMVue {
        constructor(options) {
           this._virtualDOM = getDomByVirtualDOM(document.querySelector(options.el))
           this.el = this.domTemp = document.querySelector(options.el)
           this.data = options.data()
           this.render()
        }
        render(){
          this.compiler()
        }
        compiler(){
          console.log("原始dom",this.el) // 原始dom
          console.log("生成的虚拟dom",this._virtualDOM) // 基于原始dom 生成的虚拟dom
          let temp = getVirtualDOMByDom(this._virtualDOM,this.data)
          console.log('虚拟dom编译生成真实DOM',temp) // 虚拟dom 编译后生成的 真实dom
          this.update(temp) // 更新挂载
        }
        update(temp){
           this.domTemp.parentNode.replaceChild(temp,this.domTemp)
        }
      }
      
      let vm = new SMVue({
        el:"#app",
        data () {
          return {
            user:{
              name:"昭阳",
              age:"25",
              ah:{
                yy:"游泳"
              }
            },
            age:55,
            flag:true
          }
        }
      })
   </script>
</body>
</html>

compiler.js 虚拟DOM的主要逻辑

let kuohaoFiler = /\{\{(.+>?)\}\}/g   // 把{{name}} 分解成name 
//  虚拟dom
class VNode {
   constructor(tag,type,data,value){
      this.tag = tag && tag.toLowerCase()
      this.type = type
      this.data = data
      this.value = value
      this.children = []
   }
   appendChild(vnode){
     this.children.push(vnode)
   }
 }
// 废弃函数 - 这个模板的逻辑已经写在 getVirtualDOMByDom
function getTmepByCompiler (node, data) {
   let nodes = node.childNodes
   nodes.forEach(item => {
      if (item.nodeType === 1) {
         this.getTmepByCompiler(item, data)
      } else if (item.nodeType === 3) {
         let txt = item.nodeValue
         txt.replace(kuohaoFiler, (_, g) => {
            item.nodeValue = getDeepAnalysis(g, data)
         })
      }
   });
   return node
}

// dom转换成虚拟dom
function getDomByVirtualDOM (node) {
   let nodeType = node.nodeType
   let nodeName = node.nodeName
   let nodeValue = node.nodeValue

   let virtuaDom = {}
   if (nodeType === 1) { // 元素节点
      let attrs = node.attributes // 获取元素身上的属性 id title等
      let attrsObj = {}
      for (let i = 0; i < attrs.length; i++) {
         attrsObj[attrs[i].nodeName] = attrs[i].nodeValue
      }
      virtuaDom = new VNode(nodeName, nodeType, attrsObj, nodeValue)
      // 如果有子元素的情况
      let nodes = node.childNodes
      nodes.forEach(ele => {
         virtuaDom.appendChild(getDomByVirtualDOM(ele))
      });
   } else if (nodeType === 3) { // 文本节点
      virtuaDom = new VNode(undefined, nodeType, undefined, nodeValue)
   }
   return virtuaDom
}
// 把虚拟DOM转换成DOM
function getVirtualDOMByDom (vnode, createData) {
   let { type, tag, value, data, children } = vnode
   let _dom = null
   if (type === 1) {
      _dom = document.createElement(tag)
      for (const key in data) {
         _dom.setAttribute(key, data[key]) // data 数据通过setAttribute绑定到元素身上
      }
      children.forEach(element => {
         _dom.appendChild(getVirtualDOMByDom(element, createData))
      });
   } else if (type === 3) {
      value = value.replace(kuohaoFiler, (_, g) => {
         return getDeepAnalysis(g, createData)
      })
      _dom = document.createTextNode(value)
   }
   return _dom
}
// 解析a.b.c.d 实际是string 转obj
function getDeepAnalysis (path, data) {
   path = path.split('.')
   for (let i = 0; i < path.length; i++) {
      data = data[path[i]]
   }
   return data
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容