vue 3 的 map/set 响应式需显式包裹(如 reactive(new map())),仅对结构操作响应,内部对象属性变化不触发更新,且必须使用原生方法操作。

Vue 3 的响应式系统原生支持 Map 和 Set,但不是“开箱即用”的深层自动响应——它代理的是集合结构本身,而不是内部值的属性变化。能否响应更新,取决于你如何创建、插入和操作它们。
必须用 reactive 或 ref 显式包裹
直接将 new Map() 或 new Set() 赋值给 reactive 对象的属性,不会获得响应式能力;必须显式包裹:
- 推荐 reactive:const myMap = reactive(new Map()),后续调用 myMap.set()、myMap.delete() 等原生方法会自动触发依赖更新
- Pinia 中常用 ref:state 里写 permissions: ref(new Map()),读写都需 .value(如 this.permissions.value.set())
- 避免裸露赋值:state: { cache: new Map() } → 修改 cache.set() 不触发更新
响应式边界在“结构”,不在“内容”
Map/Set 只对增删改查这些结构操作响应,不关心内部对象字段是否变化:
递归分析 Vue 项目组件依赖,从入口文件生成组件层级图,支持 Vue 2/3,输出组件名、文件路径和属性。适用于分析组件结构、排查依赖或了解项目架构。
- myMap.set('user', { name: 'Alice' }) → 修改 user.name 不触发 map 相关模板重渲染
- myMap.set('user', reactive({ name: 'Alice' })) → user.name 变化会触发依赖该对象的 computed 或 effect,但不会让 v-for 重新执行,除非你再次读取 myMap.get('user')
- mySet.add({ id: 1, count: 0 }) → count 改变无响应;改为 add(reactive({ id: 1, count: 0 })) 后,count 变化才触发对应副作用
操作必须走原生方法,不能绕过代理
所有变更必须通过集合自身的 API,否则 Proxy 拦截失效:
- ✅ 正确:map.set(key, val)、set.add(item)、map.delete(key)、set.clear()
- ❌ 无效:map[key] = val(跳过 Proxy)、set[0] = item(Set 不支持索引赋值)、手动改 map.size
- ⚠️ 遍历时注意:v-for="[key, value] of map" 是安全的;但 Array.from(map)[0] = ... 会脱离响应链
Key 和 value 类型有讲究
尤其影响 Map 的稳定性与可追踪性:
- Map 的 key 应为原始值(字符串/数字/Symbol)或同一个 reactive 对象实例;避免每次 new Object() 作 key,会导致 has()/get() 失效
- Set 的 value 若是对象,重复 add 同一引用不会触发更新(符合 Set 语义),但不同引用即使内容相同也会被当作新值
- WeakMap / WeakSet 不支持响应式——Vue 3 明确不劫持,因其弱引用行为无法被 Proxy 安全拦截
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










