Skip to content

Object.defineProperty与Proxy #5

@twosugar

Description

@twosugar

vue2.0的双向绑定就是基Object.defineProperty,而vue3.0已将Object.defineProperty替换成了Proxy,vue做了这层改变和他们两的特性息息相关。

Object.defineProperty问题

  • Object.defineProperty无法监控到数组下标的变化,导致通过数组下标添加元素,不能实时响应(可以用一个新数组替代解决);
  • Object.defineProperty只能劫持对象的属性,从而需要对每个对象,每个属性进行遍历,如果,属性值是对象,还需要深度遍历。Proxy可以劫持整个对象,并返回一个新的对象。

Proxy特点

  • 可以劫持整个对象,并返回一个新对象
  • 有13种劫持操作
  • Proxy是es6提供的,兼容性不好,无法用polyfill磨平

用Object.defineProperty手写一个数据双向绑定案例

<body>
  hello,world
  <input type="text" id="model">
  <p id="word"></p>
</body>
<script>
  const model = document.getElementById("model")
  const word = document.getElementById("word")
  var obj= {};
  Object.defineProperty(obj, "model", {
    get: function() {
       return model.value
    },
    set: function(newValue) {
      model.value = newValue
      word.innerHTML = newValue
    }
  })
  document.addEventListener("keyup",function(e){
    obj.model = e.target.value
  })
</script>

Proxy例子

<body>
  hello,world
  <input type="text" id="model">
  <p id="word"></p>
</body>
<script>
  const model = document.getElementById("model")
  const word = document.getElementById("word")
  var 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('setting',target, key, value, receiver);
        if (key === "text") {
          model.value = value;
          word.innerHTML = value;
        }
        return Reflect.set(target, key, value, receiver);
      }
    });

  model.addEventListener("keyup",function(e){
    newObj.text = e.target.value
  })
</script>

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions