数据响应原理(一)

92 阅读1分钟

MVVM

mode<=view-model=>view

非侵入式

直接修改输入 调用方法才能更新数据(侵入式)

Object.defineProperty()

数据劫持、数据代理,可以设置对象隐藏属性

  • writable -true- 是否可改变
  • enumerable -false- 是否可遍历
  • configurable -false- 属性的描述符才能够被改变,同时该属性也能从对应的对象上被删除。
  • value -undefined- 正常的属性
  • get() 拦截get 不能与value 同时出现 。执行时不传入任何参数,但是会传入 this 对象(由于继承关系,这里的this并不一定是定义该属性的对象)。该函数的返回值会被用作属性的值。
  • set() 拦截set。当属性值被修改时,会调用此函数。该方法接受一个参数(也就是被赋予的新值),会传入赋值时的 this 对象。
let object1 = {}
Object.defineProperty(object1, 'property1', {
  value: 42,
  writable: false // 是否可写
});

Object.defineProperty(object1, 'property2', {
    // getter
    get() {
        console.log('object1.property2-----------------被读')
    },
    // setter
    set(){
        console.log('object1.property2-----------------设置')
    } 
});
// 中转
let temp = ''
Object.defineProperty(object1, 'property3', {
    // getter
    get() {
        // return temp 中转的变量 
        return 3
    },
    // setter
    set(newVal){
        // temp = newVal 中转的变量
    } 
});
console.log(object1.property2)
object1.property2++
object1.property2 = 10
console.log(object1.property2, '实际未设置')// undefined
object1.property3 = 10
console.log(object1.property3, '修改值依旧返回 固定值,需要用个变量中转')



// defineReactive
let obj = {}
const defineReactive = function (obj, key, val) {
  Object.defineProperty(obj, key, {
    configurabletrue,
    enumerabletrue,
    // getter
    get() {
       console.log('-----------------访问属性', key, ':', val)
       return val
    },
    // setter
    set(data) {
      if (val === data) {
        return false
       }
      console.log('-----------------设置属性', key, ':', val)
      val = data
    } 
});
}
defineReactive(obj, 'a'10)
defineReactive(obj, 'b'20)
console.log(++obj.a)
console.log(obj.b)