vue源码阅读 之 set

主要使用场景,响应式对象上新增 property 时 vue无法探测到新增的 property, 向vue对象中添加一个 property 且刷新视图

export function set(target: Array | Object, key: any, val: any): any {
  // 开发环境 且 null | string | number | symbol | boolean 提示
  if (
    process.env.NODE_ENV !== "production" &&
    (isUndef(target) || isPrimitive(target))
  ) {
    warn(
      `Cannot set reactive property on undefined, null, or primitive value: ${(target: any)}`
    );
  }
  // 当 target 为数组 且 key 为有效 key 的时候
  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属性
  const ob = (target: any).__ob__;
  // 判断是否为 vue实例 或者 存在 ob 对象 且 含有 vmCount 属性
  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;
  }
  // 增加对应 key 的响应事件
  defineReactive(ob.value, key, val);
  // 推送对应的订阅消息
  ob.dep.notify();
  // 返回结果
  return val;
}

总结:

  • 数组,替换key对应的val并返回最新结果
  • 对象:
    • key存在对象的属性上时,替换key对应的val并返回最新结果
    • vue实例 或者 存在vmCount属性时,直接返回val
    • 非响应式对象时,直接返回val
    • 响应式对象,且key不存在prototype上时,增加对应的事件,返回对应的val

你可能感兴趣的:(vue源码阅读 之 set)