vue得$set原理

话不多说上源码,其实问题就是在于修改数组例如 arr=[1,2,3,4] arr[1]=2,类似这种直接用下标修改整个值得无效, 如果式arr=[{name:“aaa”}] arr[0].name="ccc"这种是可以得 arr[0]={name:“ccc”} 这是不行得

**

  • 源码

**

function set (target: Array<any> | Object, key: any, val: any): any {
  if (process.env.NODE_ENV !== 'production' &&
    (isUndef(target) || isPrimitive(target))
  ) {
    warn(`Cannot set reactive property on undefined, null, or primitive value: ${(target: any)}`)
  }
  // 数组
  if (Array.isArray(target) && isValidArrayIndex(key)) {
    target.length = Math.max(target.length, key)
    target.splice(key, 1, val)
    return val
  }
  // 对象
  if (key in target && !(key in Object.prototype)) {
    target[key] = val
    return val
  }
  const ob = (target: any).__ob__
  if (target._isVue || (ob && ob.vmCount)) {
    process.env.NODE_ENV !== 'production' && warn(
      'Avoid adding reactive properties to a Vue instance or its root $data ' +
      'at runtime - declare it upfront in the data option.'
    )
    return val
  }
  if (!ob) {
    target[key] = val
    return val
  }
  defineReactive(ob.value, key, val)

首先warn警告我们可以忽略

1.第一先判断是否为数组
如果是得话,他将目标对象得长度设为target.length, key两者大得那一个,通过splice方法去修改。
问题就在这splice方法如何响应,其实vue在初始化数据得时候会将数据通过object.defineproperty来做一个响应式处理,数组比较特殊,需要通过修改他得原型链,重写数组得方法来实现响应式,下面第二份代码

// 数组
  if (Array.isArray(target) && isValidArrayIndex(key)) {
    target.length = Math.max(target.length, key)
    target.splice(key, 1, val)
    return val
  }

重写得方法中去将对应得值响应式化,然后再调用原型链上对应得方法就可以了

// 扩展数组得方法 使其响应式变化    这里就例举4个方法
let ARRAY_METHOD = ["push", "pop", "shift", "unshift"];
// 继承关系 arr->Array.prototype->Object.prototype.....
// 修改继承关系 arr->改写得方法->Array.prototype->Object.prototype.....
// 创建一个对象
let array_method = Object.create(Array.prototype);
ARRAY_METHOD.forEach((method) => {
    // 重写array_method中得对应方法 函数拦截
    array_method[method] = function () {
        // 将数据响应式化  arguments代表push 进来得值 比如{name:“111”}
        for (let item of arguments) {
            Observer(item);
        }

        // 调用原来得方法 Array.prototype[method] 正常操作
        let res = Array.prototype[method].apply(this, arguments);
        return res;
    };
});

2.第二部 判断对象这个没什么好说得vue本就支持对象得响应式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值