Vue.set 方法原理

javascript 复制代码
function set(target, key, value) {
  // 判断是否是数组,并且 key 是一个有效的索引值
  if (Array.isArray(target) && isValidArrayIndex(key)) {
    target.length = Math.max(target.length, key)
    target.splice(key, 1, value)
    return value
  }
  
  // 判断 key 是否已经存在于 target 中
  if (key in target && !(key in Object.prototype)) {
    target[key] = value
    return value
  }
  
  // 获取 target 的响应式对象
  const ob = target.__ob__
  
  // 判断 target 是否是响应式对象
  if (target._isVue || (ob && ob.vmCount)) {
    // 非生产环境下发出警告,不能给 Vue 实例或根数据对象添加新的 property
    // 因为 Vue 实例是代理了根数据对象,并且 Vue.set 无法触发视图更新
    console.warn(
      'Avoid adding reactive properties to a Vue instance or its root $data ' +
      'at runtime - declare it upfront in the data option.'
    )
    return value
  }
  
  // 如果 target 不是响应式对象,直接将 key 和 value 添加到 target 中
  if (!ob) {
    target[key] = value
    return value
  }
  
  // 将 key 添加到 target 中,并将 key 设置为响应式
  defineReactive(ob.value, key, value)
  ob.dep.notify()
  return value
}

上述代码中首先判断了 target 是否是数组,并且 key 是一个有效的索引值,如果满足条件,则使用 splice 方法将 value 添加到 target 中。

接着判断了 key 是否已经存在于 target 中,如果存在,则直接更新 target[key] 的值。

然后判断了 target 是否是 Vue 实例或根数据对象,如果是,则发出警告,不能给 Vue 实例或根数据对象添加新的 property。

最后判断了 target 是否是响应式对象,如果是,则使用 defineReactive 方法将 key 添加到 target 中,并将 key 设置为响应式。

相关推荐
IT_陈寒4 分钟前
SpringBoot项目启动慢?5个技巧让你的应用秒级响应!
前端·人工智能·后端
树上有只程序猿38 分钟前
2026低代码选型指南,主流低代码开发平台排名出炉
前端·后端
橙某人1 小时前
LogicFlow 小地图性能优化:从「实时克隆」到「占位缩略块」!🚀
前端·javascript·vue.js
高端章鱼哥1 小时前
为什么说用OpenClaw对打工人来说“不划算”
前端·后端
大脸怪1 小时前
告别 F12!前端开发者必备:一键管理 localStorage / Cookie / SessionStorage 神器
前端·后端·浏览器
Mr_Mao1 小时前
我受够了混乱的 API 代码,所以我写了个框架
前端·api
小徐_23331 小时前
向日葵 x AI:把远程控制封装成 MCP,让 AI 替我远程控制设备
前端·人工智能
boooooooom1 小时前
讲清 Proxy + effect + track/trigger 流程
javascript·vue.js·面试
冴羽1 小时前
来自顶级大佬 TypeScript 之父的 7 个启示
前端·typescript
leafyyuki1 小时前
在 Vue 项目中玩转 FullCalendar:从零搭建可交互的事件日历
前端·javascript·vue.js