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 设置为响应式。

相关推荐
人工智能训练师1 小时前
Ubuntu22.04如何安装新版本的Node.js和npm
linux·运维·前端·人工智能·ubuntu·npm·node.js
Seveny071 小时前
pnpm相对于npm,yarn的优势
前端·npm·node.js
yddddddy2 小时前
css的基本知识
前端·css
昔人'2 小时前
css `lh`单位
前端·css
前端君3 小时前
实现最大异步并发执行队列
javascript
Nan_Shu_6144 小时前
Web前端面试题(2)
前端
知识分享小能手4 小时前
React学习教程,从入门到精通,React 组件核心语法知识点详解(类组件体系)(19)
前端·javascript·vue.js·学习·react.js·react·anti-design-vue
蚂蚁RichLab前端团队5 小时前
🚀🚀🚀 RichLab - 花呗前端团队招贤纳士 - 【转岗/内推/社招】
前端·javascript·人工智能
孩子 你要相信光5 小时前
css之一个元素可以同时应用多个动画效果
前端·css
萌萌哒草头将军5 小时前
Oxc 和 Rolldown Q4 更新计划速览!🚀🚀🚀
javascript·vue.js·vite