2021-03-15

手写一个简单的vue数据驱动原理

Vue与模板

  1. 编写一个模板
    如何去编写一个模板,
    1、直接在html标签中写标签
    2、使用 template
    3、在单文件中使用template
  2. 创建一个Vue实例
  3. 将Vue 挂载到页面上
<!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>
  <script src="../js/vue.js"></script>
</head>

<body>
  <!-- 写模板  -->
  <div id="root">
    <p>{{ name }}</p>
    <p>{{ message }}</p>
  </div>

  <script>
  console.log(root); //没有替换之前的模板
    //  第二步 创建vue实例 
    let app = new Vue({
      el: "#app",
      data: {
        name: '张三',
        message: "是一个男人"
      }
    })

    // 第三步 是挂载 这种写法 在 vue js中已经帮我们实现了挂载
      console.log(root);// 替换之后的模板
  </script>
</body>

</html>
那么我们自己如何去实现这样一个过程呢,在当前案列中,模板其实就是一个html元素,在vue源码中模板其实是一个字符串,Vue所做的就是,DOM => 字符串模板 =>  虚拟DOM => 真实DOM ,首先我们先来做一下步骤拆解
  1. 拿到模板DOM元素
  2. 获取数据
  3. 数据与模板结合,得到的就是DOM
  4. 放在页面中
<!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>实现简单的vue数据驱动</title>
</head>

<body>
  <!-- 写模板  -->
  <div id="root">
    <div>
      <div>
        <p>{{name}}{{message}}</p>
      </div>
    </div>
    <p>{{ name }}</p>
    <p>{{ message }}</p>
  </div>

  <script>
  // 获取当前的模板 
  let temNode = document.getElementById("root");
   // 复制一个模板出来  因为是DOM元素可以这么做
  let clonetemNode = temNode.cloneNode(true);
  
    // 定义一个数据
    let data = {
      name: '一个新的name',
      message: '一个新的message'
    };
    // 如何将数据放入模板中 
    // 一般使用递归
    let rkuohao = /\{\{(.+?)\}\}/g;
    function compiler(template, data) {
      // 遍历他下面的子节点 
      let childrenNodes = template.childNodes;
      for (let i = 0; i < childrenNodes.length; i++) {
        //循环 判断是否是元素节点 还是文本节点 1是元素节点 3是文本节点 元素节点的nodeValue是没有意义的 文本节点的nodeName是没有意义的
        let type = childrenNodes[i].nodeType;
        if (type === 3) {
          // 文本节点就去判断里面有没有 {{}}
          let txt = childrenNodes[i].nodeValue;// 获取文本节点里面的值 
          // 有没有 {{}}
          txt = txt.replace(rkuohao, function (_, g) {
            let key = g.trim();
            let value = data[key];
            return value;
          })
          // 注意现在txt与DOM没有关系 需要重新加回去
          childrenNodes[i].nodeValue = txt;

        } else if (type === 1) {
          // 元素节点的话就去判断他有没有有子元素 查看子元素是否有插值语法 用到了递归
          compiler(childrenNodes[i], data)
        }

      }

    }
    console.log(temNode)
    compiler(clonetemNode, data)
    console.log(clonetemNode)

    // 复制好的模板替换原来的DOM
    root.parentNode.replaceChild(clonetemNode, root)

    // 存在的问题
    // vue使用的是虚拟DOM
    // 只考虑了单属性{{ name }},但是在Vue中使用了大量的层级 {{ xx.xx.xx}}
    // 代码没有整合 ,Vue中使用了构造函数 

  </script>
</body>

</html>

如果有不对的地方,还请各位大佬指正。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值