一、技术背景与适用场景
1.1 设计初衷
解决跨层级组件通信难题,替代传统props逐层传递模式,特别适用于:
- 主题配置等全局状态管理
- 多级嵌套组件的数据共享
- 避免中间层组件的逻辑污染
1.2 与Vue2的差异
Vue2 vs Vue3对比
- Vue2 this.$children[0].provide('token', value)
- Vue3 provide('token', ref(value))
Vue3通过响应式代理实现自动更新,无需手动触发通知
二、核心API详解
2.1 基础用法
js
<script setup>
import { provide, ref } from 'vue'
const count = ref(0)
provide('counter', count)
// 键名建议使用字符串常量
</script>
<!-- 注入方组件 -->
<script setup>
const count = inject('counter')
</script>
2.2 高级配置
默认值处理:
js
inject('config', { theme: 'light' }) // 对象类型默认值
inject('token', 'default_token') // 基础类型默认值
类型安全(TypeScript):
js
interface UserContext {id: string role: 'admin' | 'user' }
const user = inject<UserContext>('user')
三、响应式原理与性能优化
3.1 响应式追踪
- 提供方必须使用ref/reactive包装数据
- 注入方直接读取会失去响应性,需通过.value访问
3.2 最佳实践
- 避免滥用:仅用于跨3层以上的组件通信
- 命名规范:建议使用ctx_前缀(如ctx_user)
- 性能优化:对大型对象使用shallowRef减少开销
四、典型应用场景案例
4.1 主题切换系统
js
<!-- App.vue -->
<script setup>
import { provide, ref } from 'vue'
const theme = ref('dark')
provide('theme', theme)
</script>
<!-- 任意深层组件 -->
<script setup>
const theme = inject('theme')
</script>
4.2 权限控制中间件
js
// 根组件
provide('permissions', ['read', 'write'])
// 按钮组件
const canEdit = inject('permissions').includes('write')
五、常见问题排查
- 注入失败:检查provide是否在父组件调用
- 响应性丢失:确认数据是否经过ref/reactive处理
- 类型报错:添加TypeScript类型断言