Skip to content

Latest commit

 

History

History
99 lines (91 loc) · 2.68 KB

双向绑定.md

File metadata and controls

99 lines (91 loc) · 2.68 KB

手写双向绑定

基于数据劫持的双向绑定

<!doctype html>
<html lang="en">
<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>Document</title>
</head>
<body>
  <main>
    <p>请输入:</p>
    <input type="text" id="input">
    <p id="p"></p>
  </main>
</body>
<script>
  const obj = {};
  Object.defineProperty(obj, 'text', {
    get: function() {
      console.log('get val');
    },
    set: function(newVal) {
      console.log('set val:' + newVal);
      document.getElementById('input').value = newVal;
      document.getElementById('p').innerHTML = newVal;
    }
  });

  const input = document.getElementById('input');
  input.addEventListener('keyup', function(e){
    obj.text = e.target.value;
  })
</script>
</html>

基于Object.defineProperty的双向绑定

优点:

  • 监听所有属性不需要遍历所有
  • 可以监听数组的变化
<!doctype html>
<html lang="en">
<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>Document</title>
</head>
<body>
<main>
  <p>请输入:</p>
  <input type="text" id="input">
  <p id="p"></p>
</main>
</body>
<script>
  const input = document.getElementById('input');
  const p = document.getElementById('p');
  const obj = {};

  const newObj = new Proxy(obj, {
    get: function(target, key, receiver) {
      console.log(`getting ${key}!`);
      return Reflect.get(target, key, receiver);
    },
    set: function(target, key, value, receiver) {
      console.log(target, key, value, receiver);
      if (key === 'text') {
        input.value = value;
        p.innerHTML = value;
      }
      return Reflect.set(target, key, value, receiver);
    },
  });

  input.addEventListener('keyup', function(e) {
    newObj.text = e.target.value;
  });
</script>
</html>

Vue2到Vue3的变化

从Object.definedProperty到Proxy

  • 无法监听利用索引直接设置数组的一个项,例如:vm.items[indexOfItem] = newValue
  • 无法监听数组的长度的修改,例如:vm.items.length = newLength
  • 无法监听 ES6 的 Set、WeakSet、Map、WeakMap的变化
  • 无法监听 Class 类型的数据;
  • 无法监听对象属性的新加或者删除;

参考

面试官: 实现双向绑定Proxy比defineproperty优劣如何? JavaScript 设计模式精讲 - 第三章 11代理模式