1-0 【数据驱动】:仿 vue 实现一个简单的数据驱动

171 阅读1分钟

一、模拟 vue,自己写 一个数据驱动

自己写一个类似的 vue 简单的数据驱动,和 vue 源码类型, 有以下4个步骤

  • 获取模板
  • 创建数据
  • 将数据与模板结合,得到是 HTML 元素(DOM 元素)
  • 把 DOM 元素放到页面中
<body>
  <!-- 1. 创建模板 -->
  <div id="root">
    <div>
      <div>
        <p>{{name}}--{{message}}</p>
      </div>
    </div>
    <p>{{name}}</p>
    <p>{{message}}</p>
  </div>

  <script>
    // 2. 获取模板
    let temNode = document.querySelector('#root');
    // 3. 获取数据
    let data  = {
      name: '姓名',
      message: '消息'
    }
    let rKuohao = /{\{(.+?)\}\}/g;
    // 4. 将数据与模板结合,生成 dom 渲染到页面中。
    function compiler(template, data) {
      // 获取到该模板的所有子元素,通过对子元素进行遍历,
      // 文本节点通过正则来匹配{{}},对{{}}进行 data 赋值
      // 元素节点通过递归来对它的子元素再次遍历
      let childNodes = template.childNodes;
      for(var i = 0; i<childNodes.length; i++) {
        let nodeType = childNodes[i].nodeType;
        if(nodeType === 3) {
          let txt = childNodes[i].nodeValue;
          /*
          * replace 使用正则匹配一次, 函数就会被调用一次
          * 函数的 第 0 个参数,表示 匹配到的内容
          * 函数的 第 n 个参数,表示 正则中的第 n 组
          */
          txt = txt.replace(rKuohao, (_, val) => {
            let key = val;
            let value = data[key];
            return value;
          })
          childNodes[i].nodeValue = txt;

        } else if (nodeType == 1) {
          compiler(childNodes[i], data)
        }
      }
    }
    
    // 因为 dom 是引用类型, 通过 cloneNode 复制一个新的 dom, 模板 tmpNode 不会受到影响
    let generateNode = temNode.cloneNode(true);
    compiler(generateNode, data);
    // 把生成的 dom 渲染到页面中去
    root.parentNode.replaceChild(generateNode, root);
    console.log(temNode, '模板')
    console.log(generateNode, '新的dom')

  </script>
</body>

二、以上有几个问题:

  1. 代码没有整合
  2. 只考虑了单属性,没有考虑到稍微复杂层级的属性,如 {{child.name.firstName}}
  3. vue 是虚拟 DOM, 我们的是真实 DOM