简易 Vue 构建--篇一

真实 DOM 中的模板数据替换
<!DOCTYPE html>
<!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>
  <body>
    <div id="root">
      <div>111{{name.firstName}}-{{age}}</div>
      <p>
        <span>{{name.lastName}}</span>
      </p>
    </div>
    <script>
      // #4.2 对象解析函数 a.b.c.d这种格式
      function getValueByKey(obj, str) {
        const arr = str.split('.')
        let prop = null
        while ((prop = arr.shift())) {
          obj = obj[prop]
        }
        return obj
      }

      const reg = /\{\{(.+?)\}\}/g
      function compiler(template, data) {
        // 拿到根节点下的所有子节点
        const childNodes = template.childNodes || []
        // #4.1循环子节点
        for (let i = 0; i < childNodes.length; i++) {
          // 拿到子节点标签 类型
          const nodeType = childNodes[i].nodeType
          if (nodeType === 1) {
            // 标签节点 静态模板
            // 递归
            compiler(childNodes[i], data)
          } else if (nodeType === 3) {
            // 文本节点
            // 文本值
            const txt = childNodes[i].nodeValue
            // 正则替换
            const value = txt.replace(reg, function (_, g) {
              const key = g.trim()
              // return data[key]
              return getValueByKey(data, key)
            })
            childNodes[i].nodeValue = value
          }
        }
      }

      function OVue(obj) {
        // 习惯: 内部的数据使用下划线 开头, 只读数据使用 $ 开头

        // 根元素
        this._el = obj.el
        // 数据
        this._data = obj.data

        // 根模板
        this._template = document.querySelector(this._el)
        // ? 为什么要拿父节点
        this._parent = this._template.parentNode

        // #2 调用render函数更新视图
        this.render()
      }

      // 渲染函数
      OVue.prototype.render = function () {
        this.compiler()
      }
      
      // 编译解析{{}} 模板与数据结合 得到 真正的 DOM 元素
      OVue.prototype.compiler = function () {
        // #3 拷贝原HTML DOM 节点
        const tmpRootCln = this._template.cloneNode(true)
        // #4 使用拷贝的 DOM 节点 进行数据替换
        compiler(tmpRootCln, this._data)
        // #5 更新 DOM
        this.update(tmpRootCln)
      }
      
      // 更新视图
      OVue.prototype.update = function (tmpRootCln) {
        this._parent.replaceChild(tmpRootCln, this._template)
      }

      // #1 创建实例
      new OVue({
        el: '#root',
        data: {
          name: { firstName: 'wang', lastName: 'wu' },
          age: 18
        }
      })
    </script>
  </body>
</html>
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值