4. Vue的API-$set和$delete的原理

由于Vue2.6.*之前侦测数据变化都是经过Object.defineProperty实现,ES6以前都没法提供元编程能力,因此没法侦测对象的增长和删除属性,这个时候须要单独对其进行处理。vue

set处理新增的属性

set方法的做用是在object或者Array上设置一个属性, 在Vue的原型上添加方法Vue.prototype.$set = set, set方法具体实现为:react

function set (target, key, val) {
    if (isUndef(target) || isPrimitive(target)
    ) {
      warn(("Cannot set reactive property on undefined, null, or primitive value: " + ((target))));
    }
    // 对数组,直接添加, 触发前面讲到的splice拦截器
    if (Array.isArray(target) && isValidArrayIndex(key)) {
      target.length = Math.max(target.length, key);
      target.splice(key, 1, val);
      return val
    }
    //  key已经存在于target中,已经被侦测了变化,就能够发送依赖通知
    if (key in target && !(key in Object.prototype)) {
      target[key] = val;
      return val
    }
    // 经过获取ob来判断target是不是响应式的
    var ob = (target).__ob__;
    // 经过_isVue的属性来判断target是不是vue的实例
    if (target._isVue || (ob && ob.vmCount)) {
      warn(
        'Avoid adding reactive properties to a Vue instance or its root $data ' +
        'at runtime - declare it upfront in the data option.'
      );
      return val
    }
    // 不存在__ob__属性就不作处理
    if (!ob) {
      target[key] = val;
      return val
    }
    //  转化为getter/setter形式,并向target的依赖通知变化
    defineReactive$$1(ob.value, key, val);
    ob.dep.notify();
    return val
  }
复制代码

del方法原理

del方法能够删除Object或者Array的某个属性,在Vue原型上挂载Vue.prototype.$delete = del;编程

/**
   * Delete a property and trigger change if necessary.
   */
  function del (target, key) {
    // 若是是数组,则直接删除
    if (Array.isArray(target) && isValidArrayIndex(key)) {
      target.splice(key, 1);
      return
    }
    // 与set方法一致
    var ob = (target).__ob__;
    if (target._isVue || (ob && ob.vmCount)) {
      warn(
        'Avoid deleting properties on a Vue instance or its root $data ' +
        '- just set it to null.'
      );
      return
    }
    // 若是key不是target的属性则直接返回
    if (!hasOwn(target, key)) {
      return
    }
    // 删除属性
    delete target[key];
    // 若是不是响应式数据,则返回
    if (!ob) {
      return
    }
    // 为响应式数据的话,则通知依赖更新
    ob.dep.notify();
  }
复制代码

这部分介绍了侦测数据的API,computed的实现原理在后面的初始化过程再介绍。数组

相关文章
相关标签/搜索