Vue-$set内部实现浅析

1、使用场景

首先我们来看看官网如何说明的:由于 JavaScript 的限制,有些 Vue 无法检测的更改类型。但是,有一些方法可以规避它们以维持响应性。

  • 对于对象
    Vue 无法检测到 property 的添加或删除。由于 Vue 在实例初始化期间执行 getter/setter 转换过程,因此必须在 data 对象中存在一个 property,以便 Vue 对其进行转换并使其具有响应式。

    对于已经创建的实例,Vue 不允许动态添加根级别的响应式 property。但是,可以使用 Vue.set(object, propertyName, value) 方法向嵌套对象添加响应式 property,还可以使用 vm.$set 实例方法

  • 对于数组
    Vue 不能检测以下数组的变动:
    当你利用索引直接设置一个数组项时,例如:vm.items[indexOfItem] = newValue
    当你修改数组的长度时,例如:vm.items.length = newLength

    此时可以使用Vue.set(vm.items, indexOfItem, newValue)

详情可见官网相关描述

2、内部实现

下面我们再来看看$set内部到底是这么实现的:
在vue/dist/vue.js里找到了如下源码

function set (target, key, val) {
    if (isUndef(target) || isPrimitive(target)
    ) {
      warn(("Cannot set reactive property on undefined, null, or primitive value: " + ((target))));
    }
    // 1、判断isArray且不包含key 通过splice
    if (Array.isArray(target) && isValidArrayIndex(key)) {
     // 修改数组的长度, 避免索引>数组长度导致splcie()执行有误
      target.length = Math.max(target.length, key);
      // 利用数组的splice变异方法触发响应式
      target.splice(key, 1, val);
      return val
    }
    // 2、target为对象, key在target或者target.prototype上。直接修改即可,
    if (key in target && !(key in Object.prototype)) {
      target[key] = val;
      return val
    }
    // 3、创建新属性
    var ob = (target).__ob__;
    if (target._isVue || (ob && ob.vmCount)) {
      // Vue 实例对象拥有 _isVue 属性, 即不允许给Vue 实例对象添加属性
      // 也不允许Vue.set/$set 函数为根数据对象(vm.$data)添加属性
      warn(
        'Avoid adding reactive properties to a Vue instance or its root $data ' +
        'at runtime - declare it upfront in the data option.'
      );
      return val
    }
    // target本身就不是响应式数据, 直接赋值
    if (!ob) {
      target[key] = val;
      return val
    }
    // 进行响应式处理
    defineReactive$$1(ob.value, key, val);
    ob.dep.notify();
    return val
  }

如有疑问或不足之处,欢迎交流指正

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值