每个组件实例调用 reactive 创建的状态对象天然独立。因每次调用均返回全新 proxy 对象,只要在 setup、data 或组合式函数内按需调用,即可确保隔离;切忌在模块顶层创建并导出,否则导致状态共享污染。

每个组件实例调用 reactive 创建的状态对象天然独立,无需额外隔离措施。
组件内部调用 reactive 即可隔离
Vue 的响应式系统基于 JavaScript 对象的代理(Proxy),每次调用 reactive() 都会返回一个全新的、独立的响应式对象。只要每个组件实例在自己的作用域内调用它,就不会共享状态。
- 函数式组件中,在
setup()内调用reactive({}),每次渲染都生成新对象 - 类组件或
defineComponent中,在setup()或data()(Options API)里初始化,也各自独立 - 避免在模块顶层或全局作用域调用
reactive并导出,否则会被所有实例共用
常见错误:意外共享同一个 reactive 对象
如果多个组件引用了同一个 reactive 返回的对象(比如从外部导入一个预创建的对象),就会导致状态污染。
- ❌ 错误示例:const sharedState = reactive({ count: 0 }); —— 导出后被多个组件 import,状态就混了
- ✅ 正确做法:把
reactive调用封装成工厂函数,每个组件调用一次
例如:
然后在组件 setup 中:const state = createCounter(); —— 每次都拿到全新实例
组合式函数(Composable)中注意状态生命周期
自定义 Hook(如 useCounter())内部若使用 reactive,必须确保每次调用都新建对象。
- ✅ 推荐写法:在函数体内直接
return reactive({ ... }) - ❌ 避免缓存响应式对象并复用(除非明确需要跨组件共享)
- 若需默认值参数,也应在 reactive 内部处理,不依赖外部传入已响应式的对象
对比 ref:reactive 本身不解决跨实例问题,但调用方式决定隔离性
reactive 和 ref 一样,关键不在 API 本身,而在调用时机和作用域。
- 两者都“按需创建”,不是“按需隔离”——隔离是开发者通过调用位置保证的
- 多个组件同时执行
reactive({ a: 1 }),得到的是两个完全无关的响应式对象,互不影响 - 这和
useState()在 React 中每次渲染独立同理,是组合式 API 的设计前提











