ReactiveFlags 是 Vue 3 响应式系统中一组以 Symbol.for 创建的内部静态符号常量,用于标记响应式对象类型与状态,如 IS_REACTIVE、IS_READONLY、RAW 等,供 proxy 拦截器和工具函数快速判断对象性质,不暴露给用户,开发者应使用 isReactive() 等官方 API 而非直接操作。

Vue.js 的响应式系统中,ReactiveFlags 是一组静态符号常量(Symbol),用于在内部标记响应式对象的类型与状态,不直接暴露给用户,但贯穿整个 reactive、readonly、shallow 等 API 的实现逻辑。理解它,是读懂 Vue 3 响应式源码的关键入口之一。
ReactiveFlags 是什么?
它是一组以 Symbol.for 创建的唯一 Symbol 值,定义在 reactivity/src/constants.ts(Vue 3.4+)或早期版本的 reactivity/src/reactive.ts 中,常见成员包括:
- IS_REACTIVE:标记该对象是否为 reactive 创建的响应式对象(即被 Proxy 包裹且拥有 get/set 拦截)
- IS_READONLY:标记是否为 readonly 创建的只读代理(禁止 set/delete,但可读)
- IS_SHALLOW:标记是否为 shallowReactive 或 shallowReadonly 创建的“浅”响应式(仅顶层属性响应,嵌套对象不转为 proxy)
- RAW:指向被代理的原始对象(即 target),用于跳过响应式拦截直接访问
-
SKIP:用于用户手动标记某个属性不应被响应式追踪(如通过
markRaw())
如何被使用?核心作用在哪?
这些标记位不是装饰用的,而是被写入 proxy 的 target 上(实际是写入 proxy 对象自身的一个不可枚举、不可配置的 Symbol 属性),供内部函数快速判断对象性质,避免重复创建 proxy 或错误拦截:
审查 Vue 管理后台的变更请求(Vue 2 + Element UI,Vue 3 + Element Plus)。重点关注最小化变更实现、上线风险检查以及回归检查清单生成。
- 在
get拦截器中,会先检查target[ReactiveFlags.IS_REACTIVE]判断是否已响应式,再决定是否收集依赖(effect) - 在
set拦截器中,若发现target[ReactiveFlags.IS_READONLY]为 true,则直接返回 false 并触发警告 -
isReactive()、isReadonly()、isProxy()等工具函数,本质就是读取对应 flag,而非 instanceof 或 constructor 判断——因为 Proxy 无法被 instanceof 检测 - 嵌套响应式时(如 reactive({ a: { b: 1 } })),对
a取值会触发reactive(),此时会先查a[ReactiveFlags.IS_REACTIVE],已有则直接返回,避免重复代理
为什么不用布尔属性或普通字符串 key?
用 Symbol 是为了绝对隔离性和安全性:
- 普通字符串 key(如
__isReactive)可能与用户数据冲突,导致误判或污染 - Symbol 是唯一值,且默认不可枚举,不会出现在
for...in、Object.keys()中,不影响用户遍历和 JSON 序列化 -
Symbol.for('vue.isReactive')支持跨 realm 共享(如 iframe 场景),保证不同 Vue 实例间 flag 含义一致
开发者需要主动操作 ReactiveFlags 吗?
不需要,也不应该。
- 所有 flag 都由 Vue 内部自动设置和读取,用户无法也不应直接读写(如
obj[ReactiveFlags.IS_REACTIVE] = true无意义且危险) - 想判断响应式状态,请始终使用官方导出的工具函数:
isReactive()、isReadonly()、toRaw()(它内部正是通过target[ReactiveFlags.RAW] || target获取原始对象) - 想跳过响应式,用
markRaw()而非手动设 flag —— 它会把ReactiveFlags.SKIP写入对象原型链上,确保后续 reactive() 跳过该对象
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










