原生实现Vue 双向绑定(小白都会)

113 阅读1分钟

Vue 的双向绑定

Vue 的双向绑定是面试超级高频的题,因为双向绑定的设计非常精妙,这次我们尝试用原生来实现一下双向绑定吧。

双向绑定指的是:
(1)用户输入的内容能够修改 Vue 实例上的数据;
(2)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>
  </head>
  <body>
    <input type="text" id="input" />
    <div><span>用户将我修改为:</span><span id="text"></span></div>
  </body>
  <script>
    // 页面视图初始化
    const input = document.querySelector("#input");
    const text = document.querySelector("#text");
    let obj = { data: 1 };
    text.innerHTML = obj.data;
    // 经过代理之后通过 p 来对代理对象的属性进行获取和设置时会触发 getter 和 setter
    const p = new Proxy(obj, {
      // 当 input 事件触发时,obj.data 被赋值,会触发setter
      // 此时就监听到了数据的变化,需要做的事刷新视图
      set: (target, property, newVal, proxyObj) => {
        console.log("setter触发了");
        text.innerHTML = newVal;
      },
    });

    // 事件绑定:用户输入的数据同步到代理对象,这样才能触发 setter
    // 注意:input 是实时触发的,而 change 事件是当 value 发生修改且输入框失焦时触发
    input.addEventListener("input", (e) => {
    // 注意是设置代理对象,才会触发 setter
      p.data = e.target.value;
    });
  </script>
</html>

总结一波

原生实现双向绑定可以通过 input 事件和 proxy 代理来实现。
(1)实时收集数据:借助输入框的 input 事件;
(2)JS 实现数据劫持:借助 ES6 新特性:将收集到的数据赋值给代理对象 p,触发 proxy 实例的 setter 方法,这样就实现了 JS 对数据变化的监听;
(3)刷新视图:在 setter 方法里面执行更新视图的函数,上面因为只是一个 Demo ,所以直接使用 innerHTML 来更新,实际情况中要结合发布订阅模式来实现数据驱动 UI 更新。