Vue 3响应式中IS_REACTIVE标记何时被设置为true?
Vue3响应式中IS_REACTIVE标记的实现逻辑
首先要明确:IS_REACTIVE这类标记并不是直接添加到目标对象(target)本身的,而是通过Proxy的拦截器动态返回的——这就是你用hasOwnProperty查不到该属性,但直接取值能得到true的核心原因。
在createReactiveObject函数创建Proxy实例时,会传入对应的拦截器handler(比如创建普通响应式对象用的mutableHandlers),这个handler的get方法专门处理了ReactiveFlags相关的查询逻辑,核心代码来自reactivity包的baseHandlers.ts:
const get = /*#__PURE__*/ createGetter() function createGetter(isReadonly = false, shallow = false) { return function get(target: Target, key: string | symbol, receiver: object) { // 优先处理ReactiveFlags的查询 if (key === ReactiveFlags.IS_REACTIVE) { return !isReadonly } else if (key === ReactiveFlags.IS_READONLY) { return isReadonly } else if (key === ReactiveFlags.RAW) { return target // 返回原始对象 } // ...其他属性读取的响应式逻辑 } }
当你访问target[ReactiveFlags.IS_REACTIVE]时,这里的target其实是Proxy实例(而非原始对象),会触发Proxy的get拦截器:匹配到ReactiveFlags.IS_REACTIVE这个key后,直接根据当前是否为只读对象返回对应布尔值——对于reactive创建的对象,isReadonly为false,所以返回true。
而调用target.hasOwnProperty(ReactiveFlags.IS_REACTIVE)时,同样会被Proxy拦截,最终查询的是原始对象是否拥有该属性,显然原始对象并没有这个标记,因此返回false。
回到你贴出的代码片段:
if ( target[ReactiveFlags.RAW] && !(isReadonly && target[ReactiveFlags.IS_REACTIVE]) ) { console.log('keys ', target.hasOwnProperty(ReactiveFlags.IS_REACTIVE)) // 'keys ' false console.log( 'target[ReactiveFlags.IS_REACTIVE] ', target[ReactiveFlags.IS_REACTIVE] ) // 'target[ReactiveFlags.IS_REACTIVE] ' true return target }
这里的target是Proxy实例,两种不同的查询方式触发了不同的拦截逻辑,才出现了看似矛盾的结果。
总结:
- IS_REACTIVE标记从未被“添加”到目标对象上
- 它是通过Proxy的get拦截器,在被访问时动态计算并返回的
- 对应的处理逻辑在
baseHandlers.ts的createGetter函数中
内容的提问来源于stack exchange,提问作者Bippan Kumar
相关产品推荐
相关产品推荐

