简单讲解Object.defineProperty 是如何实现数据代理?

70 阅读1分钟

Object.defineProperty

Vue2框架就是基于Object.defineProperty实现数据响应式的 先来了解一下Object.defineProperty() 方法

Object.defineProperty( obj , prop , descriptor)

obj 要定义的对象(谁代理,代理者)

prop 要修改,添加的属性(代理什么,代理数据)

descriptor 属性描述(控制属性是否可以被操作,以及 getter 和 setter 方法)

那么知道了这个方法,就来看个代码吧!

let object1 = {};
let initvalue = ''
Object.defineProperty(object1,'name',{
    // value:'zhangsan',
    // writable:true, //控制属性是否可以被修改,默认为false
    enumerable:true, //控制属性是否可以被读取,默认为false
    configurable:true, //控制属性是否可以被删除,默认为false

    //当读取object1的name属性时。调用get()函数,返回name值
    get(){
      return initvalue
    },
    //当修改object1的name属性时,调用set()函数,返回name值
    set(val){
      initvalue = val
    }
});
object1.name = 'wangwu'
console.log(object1.name); // wangwu

vue中的数据代理

建立一个vue实例,名为vm,vm代理data属性,因此可以直接在控制台输入比如vm.name, vm会用getter方法输出data里的name值。 代理方法:用Object.defineProperty()方法在 vm 中添加(代理)data属性,写好相关getter、setter方法。

class Vue {
  $options;
  _data;
  constructor(options) {
    this.$options = options;
    this._data = options.data;
    this.initData()
  }

  initData() {
    let keys = Object.keys(this._data)
    for (let i in keys) {
      let key = keys[i];
      Object.defineProperty(this, key, {
        enumerable: true,
        configurable: true,
        get() {
          return this._data[key]
        },
        set(val) {
          this._data[key] = val
        }
      })
    }

  }
}

let vm = new Vue({
  data: { name: '张三', age: 21 }
})

vm.name = '李四'  //更改vm中的name
console.log(vm.name);//李四