组合式函数注入实现模块级状态共享,状态驻留闭包、全局复用;provide/inject 为声明式依赖传递,需祖先提供、后代注入,适合只读配置透传。

Vue 组合式函数注入和组件级 provide/inject 都用于跨层级共享状态与逻辑,但作用域、复用方式和响应式管理机制有本质区别。关键不在“能不能传数据”,而在于“谁持有状态、谁决定生命周期、谁负责响应式更新”。
组合式函数注入:模块级状态 + 逻辑封装
组合式函数(如 useUserStore() 或 useMouse())本身不依赖组件实例,其内部创建的 ref 或 reactive 对象驻留在模块闭包中。所有调用该函数的组件,获取的是同一份响应式实例。
- 状态不随组件挂载/卸载重置,天然支持全局或页面级共享
- 无需在父组件显式
provide,子组件直接import并调用即可接入 - 可自由组合多个组合式函数,比如
useAuth()+useNotifications(),逻辑解耦清晰 - 副作用(如事件监听、定时器)通常绑定到当前组件生命周期,由
onMounted/onUnmounted自动清理
组件 provide/inject:声明式依赖传递
provide 必须在祖先组件的 setup() 或 provide 选项中同步执行;inject 必须在后代组件的 setup() 中调用。它不创建新状态,只是把已有的响应式对象(或普通值)沿组件链向下“曝光”。
- 注入的值默认非响应式——若提供的是原始值(如字符串、数字),后代组件无法响应变化;需显式提供
ref或reactive对象才能保持响应性 - 支持 key 冲突覆盖:离得近的祖先组件提供的同名
key会覆盖更上层的值 - 适合配置透传(如主题、i18n 实例)、上下文环境(如表单校验器、编辑器上下文)等“只读+可覆盖”场景
- 无法脱离组件树存在,不能像组合式函数那样在非 setup 环境(如工具函数、测试 mock)中直接使用
响应式行为的关键差异
组合式函数返回的 ref 是响应式源头,组件直接使用不会丢失响应性;而 inject 返回的值是否响应,完全取决于 provide 时传入的对象类型:
- 若
provide('count', ref(0))→inject('count')得到的是响应式 ref,解构后需保留.value - 若
provide('config', { theme: 'dark' })→inject('config')得到的是普通对象,修改不会触发更新 - 组合式函数可主动包装非响应式输入(如把 props 或 inject 结果转为 ref),provide/inject 则不做任何转换
选型建议
需要跨多个无关组件共享可变状态?优先写组合式函数。需要给深层子组件统一注入不可变配置或上下文能力?用 provide/inject 更轻量、意图更明确。两者也可协作:组合式函数内部用 inject 获取外部上下文,再封装成带业务语义的 API。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











