zoukankan      html  css  js  c++  java
  • vue3双向数据绑定原理_demo

    <!DOCTYPE html>
    <head>
      <meta charset="UTF-8" />
      <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0" />
      <meta http-equiv="X-UA-Compatible" content="ie=edge" />
      <title>proxyVue</title>
      <style>
        #app {
                margin: 100px auto 0 auto;
                 300px;
            }
            #btn {
                margin: 10px auto;
            }
        </style>
    </head>
    
    <body>
      <div id="app">
        <input type="text" v-model="num" />
        <input id="btn" type="button" value="添加到Todolist" v-click="addList" /><br />
        <span>您输入的是:</span><span v-bind="num"></span><span>{{num}}</span>
        <ul id="list"></ul>
      </div>
    </body>
    
    <script>
      class proxyVue {
        constructor(options) {
          this.$options = options || {};
          this.$methods = this._methods = this.$options.methods;
          const data = (this._data = this.$options.data);
          this.subscribe = {};
          this.observe(data);
          this.compile(options.el);
        }
        publish(watcher) {
          if (!this.subscribe[watcher.property])
            this.subscribe[watcher.property] = [];
          this.subscribe[watcher.property].push(watcher);
        }
        observe(data) {
          const that = this;
          let handler = {
            get(target, property) {
              return target[property];
            },
            set(target, property, value) {
              let res = Reflect.set(target, property, value);
              that.subscribe[property].map(item => {
                item.update();
              });
              return res;
            }
          };
          this.$data = new Proxy(data, handler);
        }
        compile(el) {
          const nodes = Array.prototype.slice.call(
            document.querySelector(el).children
          );
          let data = this.$data;
          nodes.map(node => {
            if (node.children.length > 0) this._complie(node);
            if (node.hasAttribute("v-bind")) {
              let property = node.getAttribute("v-bind");
              this.publish(new Watcher(node, "innerHTML", data, property));
            }
            if (node.hasAttribute("v-model")) {
              let property = node.getAttribute("v-model");
              this.publish(new Watcher(node, "value", data, property));
              node.addEventListener("input", () => {
                data[property] = node.value;
              });
            }
            /**
             self ...
            */
            if (/{{(.*?)}}/.test(node.innerHTML)) {
              let ret = /{{(.*?)}}/.exec(node.innerHTML)
              let property = ret[1];
              this.publish(new Watcher(node, "innerHTML", data, property));
            }
            // self end
            if (node.hasAttribute("v-click")) {
              let methodName = node.getAttribute("v-click");
              let mothod = this.$methods[methodName].bind(data);
              node.addEventListener("click", mothod);
            }
          });
        }
      }
      class Watcher {
        constructor(node, attr, data, property) {
          this.node = node;
          this.attr = attr;
          this.data = data;
          this.property = property;
        }
        update() {
          this.node[this.attr] = this.data[this.property];
        }
      }
    
      // 渲染todolist列表
      const Render = {
        // 初始化
        init: function (arr) {
          const fragment = document.createDocumentFragment();
          for (let i = 0; i < arr.length; i++) {
            const li = document.createElement("li");
            li.textContent = arr[i];
            fragment.appendChild(li);
          }
          list.appendChild(fragment);
        },
        addList: function (val) {
          const li = document.createElement("li");
          li.textContent = val;
          list.appendChild(li);
        }
      };
    
      // 实例化一个proxyVue
      window.onload = function () {
        let vm = new proxyVue({
          el: "#app",
          data: {
            num: 0,
            arr: []
          },
          methods: {
            addList() {
              this.arr.push(this.num);
              // Render.addList(this.num);
            }
          }
        });
      };
    </script>
    
    </html>
    

      

  • 相关阅读:
    常用修图工具的一些使用技巧及问题解决方法——ai
    IIS7web服务器调试ASP.net程序遇到的一些故障的解决办法
    使用ecstore-sdk开发包制作易开店和启明星模板
    虚拟机安装Centos6.5服务器系统
    使用UltraISO制作光盘镜像
    安装配置Windows Live Writer做为博客客户端
    Winform关于OpenFileDialog的使用方法
    SQLServer的数据类型
    SqlServer把日期转换成不同格式的字符串的函数大全
    SQL字符串处理函数大全
  • 原文地址:https://www.cnblogs.com/yaxinwang/p/13827833.html
Copyright © 2011-2022 走看看