provide 和 inject 是 Vue 提供的一对"依赖注入(Dependency Injection) "机制。
它的作用是:
👉 在跨层级组件之间传递数据,
无需通过 props 一层层传递。
简单来说:
-
provide:由上层组件(祖先组件)提供数据。
-
inject:由下层组件(后代组件)接收数据。
适合场景:
当一个数据需要被很多深层子组件使用时(比如主题色、语言、配置对象等),使用 provide/inject 可以避免"多层 props 传递的麻烦"。
🧩 二、基本用法
(1)在祖先组件中提供数据
js
// App.vue
import { provide } from 'vue'
export default {
setup() {
provide('theme', 'dark')
}
}
(2)在任意后代组件中注入数据
js
// Child.vue
import { inject } from 'vue'
export default {
setup() {
const theme = inject('theme')
console.log(theme) // 输出: 'dark'
}
}
🔁 三、响应式数据的注入
provide 默认不会保持响应式。
如果你希望数据变化能被子组件自动更新,需要使用 ref 或 reactive:
js
// 父组件
import { ref, provide } from 'vue'
export default {
setup() {
const theme = ref('light')
provide('theme', theme)
return { theme }
}
}
js
// 子组件
import { inject } from 'vue'
export default {
setup() {
const theme = inject('theme')
return { theme }
}
}
✅ 这样当父组件修改 theme.value 时,子组件会自动响应更新。
🧠 四、默认值的使用
如果注入的 key 在上层没有提供,inject 会返回 undefined。
为了安全,可以给它设置一个默认值:
js
const theme = inject('theme', 'light')
或者传入一个函数返回默认值:
js
const theme = inject('theme', () => 'light')
🧮 五、在选项式 API 中使用
对于使用 data、methods 的老写法,也能用:
js
export default {
provide() {
return {
theme: 'dark'
}
},
inject: ['theme']
}
⚙️ 六、进阶:修改注入的数据
子组件如果想修改祖先组件提供的数据,要注意:
-
如果父组件提供的是普通值(非响应式),子组件改不了。
-
如果父组件提供的是 ref 或 reactive 对象,子组件可以修改。
例如:
js
// 父组件
const user = reactive({ name: 'Tom' })
provide('user', user)
// 子组件
const user = inject('user')
user.name = 'Jerry' // ✅ 可以修改
🧩 七、和 Props 的区别
对比项 | Props | Provide / Inject |
---|---|---|
用途 | 父 → 子通信 | 祖先 → 任意后代 |
层级 | 只能相邻组件 | 可跨多层级 |
响应式 | 默认响应式 | 需手动包裹 ref / reactive |
使用场景 | 一般父子通信 | 全局配置、依赖共享(如主题、国际化) |
🌈 八、实际应用场景举例
-
主题系统(Theme)
顶层组件提供主题信息,子组件统一读取。
-
表单组件库
Form 组件通过 provide 向所有子 Input 组件共享表单上下文。
-
国际化(i18n)
顶层提供语言配置,任意组件可注入读取当前语言。
🧾 九、总结一句话
provide / inject 是 Vue 组件间的"依赖注入系统 ",用于跨层级共享数据。 它的核心思想是"祖先提供,后代注入 ",适合场景是避免层层传 props,提高组件复用性。