目标:掌握跨层级组件通信的核心方式
1. 基础用法
<!-- 祖先组件 Ancestor.vue -->
<script setup>
import { provide } from 'vue' // 提供静态数据
provide('theme', 'dark') // 提供响应式数据
const count = ref(0)
provide('count', count)
</script> <!-- 后代组件 Descendant.vue -->
<script setup>
import { inject } from 'vue' // 注入数据(带默认值)
const theme = inject('theme', 'light')
const count = inject('count')
</script>
2. 响应式数据传递
<!-- 祖先组件 -->
<script setup>
import { provide, ref } from 'vue' const user = ref({ name: 'Alice' })
provide('user', user) // 提供更新方法
const updateUser = (newName) => { user.value.name = newName
}
provide('updateUser', updateUser)
</script> <!-- 后代组件 -->
<template> <button @click="updateUser('Bob')">修改用户名</button> <p>{{ user.name }}</p>
</template> <script setup>
const user = inject('user')
const updateUser = inject('updateUser')
</script>
3. 使用Symbol避免命名冲突
javascript">// keys.js
export const THEME_KEY = Symbol('theme') // 祖先组件
import { THEME_KEY } from './keys'
provide(THEME_KEY, 'dark') // 后代组件
const theme = inject(THEME_KEY)
4. 实战场景
-
主题切换:全局主题配置
-
多语言支持:全局语言包
-
用户信息:跨多层传递用户数据
-
UI组件库:配置全局默认样式
5. 注意事项
-
不要滥用:优先考虑Props/Emits,仅在多层嵌套时使用
-
响应式维护:通过
ref
/reactive
包装数据 -
类型安全:使用TS时建议定义注入数据的类型
interface User { name: string age: number
} const user = inject<User>('user')
代码规范建议:
-
对重要数据提供更新方法(而非直接修改注入值)
-
为注入数据设置合理的默认值
-
使用Symbol管理大型应用的provide key