上下文 + 事件 + 插槽链路
本章是“高级链路”示例:在一个场景中串联 provide/inject、emits、scoped slot。
1. 场景目标
- 上层页面通过
provide下发主题。 - 子组件通过
inject读取主题并触发事件。 - 父组件通过作用域插槽拿到子组件状态做二次渲染。
2. 输入示例(Vue)
vue
<!-- ParentPage.vue -->
<script setup lang="ts">
// @vr-name: ParentPage
import { provide, ref } from 'vue';
import ThemeCard from './ThemeCard.vue';
const level = ref(1);
provide('theme', 'ocean');
const onUpgrade = (next: number) => {
level.value = next;
};
</script>
<template>
<ThemeCard :level="level" @upgrade="onUpgrade">
<template #header>
<p>Header</p>
</template>
<template #footer="{ level, theme }">
<small>theme={{ theme }}, level={{ level }}</small>
</template>
</ThemeCard>
</template>vue
<!-- ThemeCard.vue -->
<script setup lang="ts">
// @vr-name: ThemeCard
import { inject } from 'vue';
const props = defineProps<{ level: number }>();
const emit = defineEmits<{ (e: 'upgrade', next: number): void }>();
const theme = inject('theme', 'default');
const upgrade = () => {
emit('upgrade', props.level + 1);
};
</script>
<template>
<section>
<slot name="header"></slot>
<p>Theme: {{ theme }}</p>
<p>Level: {{ props.level }}</p>
<button @click="upgrade">Upgrade</button>
<slot name="footer" :level="props.level" :theme="theme" />
</section>
</template>3. 输出示例(React,简化)
tsx
// ParentPage 侧:provide(...) 会转换为 Provider 包装结构
return (
<Provider name={'theme'} value={'ocean'}>
<ThemeCard
level={level.value}
onUpgrade={onUpgrade}
header={<p>Header</p>}
footer={({ level, theme }) => (
<small>
theme={theme}, level={level}
</small>
)}
/>
</Provider>
);tsx
// ThemeCard 侧:inject -> useInject, emit -> onUpgrade
const theme = useInject('theme', 'default');
const upgrade = useCallback(() => {
props.onUpgrade?.(props.level + 1);
}, [props.level, props.onUpgrade]);4. 关键说明
provide/inject走 runtime 适配,不是字符串替换。emit事件名仍建议稳定字符串。- scoped slot 在高级场景下仍是“函数型 props”语义。
下一步
- 查看 SFC 样式处理链路
