美文网首页
js实现数据双向绑定

js实现数据双向绑定

作者: _BuzzLy | 来源:发表于2020-04-27 19:00 被阅读0次

    接上一篇文章《js实现数据单向绑定
    上篇文章中用原生js实现了数据的单向绑定。本篇文章继续介绍如何用js实现数据的双向绑定。绑定的方式模仿vue中的v-model指令。

    创建标签

    <div id="div1">
      <input type="text" v-model="name">
      <br> 姓名:{{name}}
    </div>
    

    创建一个输入框,使用v-model属性绑定变量name,注意这里只是模仿vue绑定的形式,代码中并没有引入任何vue依赖。完全靠原生js实现。

    单向绑定

    let el = document.getElementById('app');
    let template = el.innerHTML;
    let _data = {
      name: '_BuzzLy'
    };
    
    let data = new Proxy(_data, {
      set(obj, name, value) {
        obj[name] = value;
        render();
      }
    });
    
    render();
    
    function render() {
      el.innerHTML = template.replace(/\{\{\w+\}\}/g, str => {
        str = str.substring(2, str.length - 2);
        return _data[str];
      });
    }
    

    到这我们又实现了一遍单向绑定,想要实现数据的双向绑定其实很简单,只需稍微修改我们的render函数。

    双向绑定

    function render() {
      el.innerHTML = template.replace(/\{\{\w+\}\}/g, str => {
        str = str.substring(2, str.length - 2);
        return _data[str];
      });
    
      // 找到所有input标签
      Array.from(el.getElementsByTagName('input'))
       // 过滤得到其中带有v-model属性的标签 
       .filter(ele => ele.getAttribute('v-model'))
       // 遍历这些input标签
       .forEach(input => {
          // 获取到v-model中绑定的key,从数据中找到key对应的value赋给input
          // 这一步就相当于数据=>视图的绑定
          let name = input.getAttribute('v-model');
          input.value = _data[name];
        
          // 为input绑定输入事件
          input.oninput = function () {
            // 当input修改时,将修改后的值赋给暴露在外的data对象
            // 这一步就实现了视图=>数据的绑定
            data[name] = this.value;
          };
      });
    }
    

    修改后的render函数通过过滤、遍历得到每一个拥有v-model属性的input标签,然后将数据绑定到视图上,并且视图修改也会触发数据的更新,这样就实现了数据的双向绑定。
    看似复杂的绑定机制其实就是通过我们熟悉的js一些基础的操作来实现的。


    完整代码

    <!DOCTYPE html>
    <html lang="en" dir="ltr">
    
    <head>
      <meta charset="utf-8">
      <title></title>
    </head>
    
    <body>
      <div id="div1">
        <input type="text" v-model="name">
        <br> 姓名:{{name}}
      </div>
    </body>
    <script>
      let el = document.getElementById('div1');
      let template = el.innerHTML;
      let _data = {
        name: '_BuzzLy'
      };
    
      let data = new Proxy(_data, {
        set(obj, name, value) {
          obj[name] = value;
          render();
        }
      });
    
      render();
    
      function render() {
        el.innerHTML = template.replace(/\{\{\w+\}\}/g, str => {
          str = str.substring(2, str.length - 2);
          return _data[str];
        });
    
        Array.from(el.getElementsByTagName('input'))
         .filter(ele => ele.getAttribute('v-model'))
         .forEach(input => {
           let name = input.getAttribute('v-model');
           input.value = _data[name];
    
           input.oninput = function () {
             data[name] = this.value;
           };
        });
      }
    </script>
    
    </html>
    

    相关文章

      网友评论

          本文标题:js实现数据双向绑定

          本文链接:https://www.haomeiwen.com/subject/qivuwhtx.html