Javascript 简单的双向绑定实现

现代 JS 中数据双向绑定 (Two-way Data Binding) 已经是一个很常见的概念了,那么双向绑定是如何实现的呢,下面就用最简单的方式实现一下这个功能。

先放代码:

HTML:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Two Way Data Binding</title>
</head>
<body>
  Name: <input v-bind="name" type="text" name="" id="name">
  <br />
  Name: <span v-bind="name"></span>
  <hr />
  City: <input v-bind="city" type="text" name="city" id="city">
  <br />
  City: <span v-bind="city"></span>
  <script src="./index.js"></script>
</body>
</html>

JS:

const elements = document.querySelectorAll('[v-bind]');
// eslint-disable-next-line no-console
console.log(elements);

const data = {};

function addProps(prop) {
  let value;
  // eslint-disable-next-line no-prototype-builtins
  if (!data.hasOwnProperty(prop)) {
    Object.defineProperty(data, prop, {
      set(newValue) {
        value = newValue;
        elements.forEach((element) => {
          const ele = element;
          if (ele.getAttribute('v-bind') === prop) {
            if (ele.type && (ele.type === 'text')) {
              // For <input> tag
              ele.value = newValue;
            } else if (!ele.type) {
              // For <span> tag
              ele.innerHTML = newValue;
            }
          }
        });
      },
      get() {
        return value;
      },
      enumerable: true,
    });
  }
}

elements.forEach((element) => {
  const ele = element;
  if (ele.type === 'text') {
    const prop = ele.getAttribute('v-bind');
    addProps(prop);
    ele.oninput = () => {
      data[prop] = ele.value;
      // eslint-disable-next-line no-console
      console.log(data);
    };
  }
});

效果预览:

效果图

解析:这个实现其实非常简单,核心有两点,一个是定义一个 data 对象来存储数据,另一个是使用 defineProperty 方法来监听该对象的变化,并在 set 和 get 操作中,修改 DOM 的值。了解了 defineProperty 的使用方法,再结合代码,不难理解这个双向绑定的实现过程。

具体 defineProperty 详细说明可以参考:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty

源码:https://github.com/tlbai/js-labs/tree/master/two-way-data-binding
参考文章:https://medium.com/frontend-fun/js-vanilla-two-way-binding-5a29bc86c787

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容