根上下文
用 defineRootContext 和 useRootContext 共享和使用根状态
根上下文用于在 App.vue 中定义应用级状态,并提供给页面、组件或应用内其他文件使用。它适合承载应用骨架相关状态,而不是替代所有业务状态管理。
能力定位
根上下文解决的是跨页面读取应用根状态的问题。
典型场景:
- 主题状态。
- 应用外壳方法。
- 应用共享弹窗。
- 应用级共享的状态。
defineRootContext
在 App.vue 中无需导入,可以直接使用 defineRootContext() 定义并返回共享状态。
src/App.vue
<script setup>
const { title, count, increment, isDark } = defineRootContext(() => {
const title = ref('Hello Oiyo')
const count = ref(0)
function increment() {
count.value += 6
}
const isDark = useSystemDark()
return { title, count, increment, isDark }
})
</script>
返回数据就是对外暴露的根上下文。这些状态可以在 App.vue 中使用,也可以被页面或其他应用文件读取。
用于定义共享状态的
defineRootContext 方法只允许在 App.vue 中使用。useRootContext
通过 useRootContext 可以在 页面、组件 或 应用内任意文件 中无需导入,直接消费 defineRootContext() 定义的共享状态。
应用骨架使用
这里的应用骨架指
App.vue 的 <template> 部分。在 App.vue 内,可以直接解构 defineRootContext() 返回的状态。
src/App.vue
<script setup>
const { increment } = defineRootContext(() => {
const count = ref(0)
function increment() {
count.value += 1
}
return { increment }
})
</script>
<template>
<view @click="increment">
触发根部叠加
</view>
</template>
应用骨架模板中使用的变量和方法都应通过
defineRootContext() 暴露。页面中使用
页面使用 useRootContext() 读取根上下文。
src/pages/home/index.vue
<script setup lang="ts">
const { title, increment } = useRootContext<{
title: Ref<string>
increment: () => void
}>()
onLoad(() => {
console.log('生命周期中使用', title.value)
})
</script>
<template>
<view>{{ title }}</view>
<view @click="increment">
模板中触发方法
</view>
</template>
应用文件中使用
store、composable 等应用内文件可以读取根上下文。
export const useAppStore = defineStore('oiyo-app', () => {
const { title } = useRootContext<{ title: Ref<string> }>()
const hey = computed(() => `你好 - ${title.value}`)
return { hey }
})
export const useCount = () => {
const { count } = useRootContext<{ count: Ref<number> }>()
const double = computed(() => count.value * 2)
return { double }
}
类型标注
defineRootContext()、useRootContext() 都支持显式标注共享状态的类型。
useRootContext() 建议显式标注当前文件需要的字段。
读取少量字段:
const { title } = useRootContext<{ title: Ref<string> }>()
读取多个字段:
interface RootContext {
title: Ref<string>
increment: () => void
}
const { title, increment } = useRootContext<RootContext>()
验证可用
检查:
defineRootContext()是否定义在App.vue。return中是否包含所需共享的状态。- 页面局部状态是否没有误放进根上下文。