vue中的数据的响应Object.defineProperty

在vue中v-model是通过Object.defineProperty来实现的,如下:

const data = {};
let name = '张三';
// 对对象定义属性
// 需要3个参数
// 参数1:对象本身
// 参数2:定义的属性
// 参数3:定义属性的选项
Object.defineProperty(data, 'name', {
  get(){
    console.log('get执行了');
    return name;
  },
  set(newVal){
    console.log('set执行了:', newVal);
    name = newVal;
  }
})
console.log(data.name);
data.name = '李四';
console.log(data.name);

上面是最简单的一种体现方法,通过对属性进行新增(Vue.set)和(Vue.delete)不能做到完全响应式。
复杂的对象,需要自己实现深度监听,进行递归监听。需要一次性监听到底的。

数量多的情况下,会导致页面卡死。 解决:vue3.0 采用 proxy polyfill

promise babel polyfill
function Promise(){
}
Promise()

对数组没有办法进行监听。需要进行额外的处理,所以数组主要是通过给数据重新定义原型,再创建新的原型,再通过循环遍历给它添加数组的一些方法

定义一个对象,封装一个函数监听对象属性
const data = {
  name: 'zhangsan',
  age: 20,
  info: {
    height: 180
  },
  list: ['a', 'b', 'c']
}
// 监听对象属性的方法
function observer(target){
  // 判断监听数据的类型
  if(typeof target !== 'object' || target === null){
    // 不是对象或者数组就被过滤了
    return target;
  }

  if(Array.isArray(target)){
    target.__proto__ = arrProto;
    return;
  }

  for( let key in target ){
    defineReactive(target, key, target[key]);
  }

}
// 监听数据的变化
observer(data);

/* data.age = {
  value: 20
}
定义原型重新创建原型调用Object.defineProperty方法并监听
function updateView(){
  console.log('视图更新了....');
}

// 重新定义数组的原型
const oldArrayProperty = Array.prototype;
// 创建新的对象,原型指向的是oldArrayProperty
// 在这个对象上扩展方法不会影响Array.prototype
const arrProto = Object.create(oldArrayProperty);
const methods = ['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse'];
// arrProto.push
// arrProto.pop
// arrProto.shift
// arrProto.unshift
// arrProto.splice
// arrProto.sort
// arrProto.reverse
methods.forEach(methodName=>{
  arrProto[methodName] = function(){
    oldArrayProperty[methodName].call(this, ...arguments);
    // 更新dom
    updateView();
  }
})
// 对每一个属性进行观测
function defineReactive(target, key, value){

  // 深度监听
  observer(value);

  Object.defineProperty(target, key, {
    get(){
      console.log('get执行了');
      return value;
    },
    set(newValue){
      console.log(key, 'set执行了');

      // 对新设置的属性值还需要进行深度监听
      observer(newValue);

      value = newValue;
      // 更新视图
      updateView();
    }
  })
}

给data改变属性验证是否发生改变

// 设置
data.info.height = 190;

data.age.value = 30; //

data.info.address = '深圳';//Vue.set

delete data.name;//Vue.delete


// data.list.push('hello');

// data.list[1] = 'xx';
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值