返回

揭开 Vue $set 神秘面纱,一探源码背后的奥秘

前端

在 Vue.js 的数据响应式系统中,set 扮演着重要的角色。它允许我们在运行时动态地向响应式对象添加或修改属性,并确保这些更改能够被 Vue.js 正确地追踪和更新。那么,set 的内部机制是什么样的呢?让我们通过源码解析来一探究竟。

第一部分:isUndef 和 isPrimitive 方法

首先,我们来看看 isUndef 和 isPrimitive 这两个方法。从名字就可以看出,isUndef 是判断 target 是否等于 undefined,而 isPrimitive 则是判断 target 是否属于原始值类型(string、number、boolean 等)。

const isUndef = (v) => v === undefined;
const isPrimitive = (value) => {
  return (
    typeof value === "string" ||
    typeof value === "number" ||
    typeof value === "boolean" ||
    typeof value === "symbol"
  );
};

第二部分:Vue.set 的实现

接下来,我们来看看 Vue.set 的实现。

export function set(target, key, val) {
  if (isUndef(target) || isPrimitive(target)) {
    throw new TypeError(
      "Cannot set reactive property on undefined, null, or primitive value: " +
        target
    );
  }
  if (Array.isArray(target) && isValidArrayIndex(key)) {
    target.length = Math.max(target.length, key);
    target[key] = val;
    return val;
  }
  const oldVal = target[key];
  if (oldVal !== val) {
    target[key] = val;
    Vue.notify(target, key, val, oldVal);
  }
  return val;
}

从代码中可以看出,Vue.set 的实现相对简单。首先,它会检查 target 是否是 undefined、null 或原始值类型。如果是,则抛出 TypeError 异常,因为这些类型的值是不可变的,无法设置响应式属性。

接下来,它会检查 target 是否是数组并且 key 是有效的数组索引。如果是,则会将 target 的长度设置为 Math.max(target.length, key),并设置 target[key] 的值为 val。

最后,如果 target[key] 的值与 val 不同,则会将 target[key] 的值更新为 val,并通知 Vue.js 进行更新。

总结

通过对 Vue.set 源码的解析,我们了解到了 set 的内部机制以及它在 Vue.js 中的作用。set 允许我们在运行时动态地向响应式对象添加或修改属性,并确保这些更改能够被 Vue.js 正确地追踪和更新。

希望这篇文章能够帮助您更好地理解 Vue.js 的数据响应式系统。如果您还有其他问题,欢迎留言讨论。