Vue 3 setup中props是响应式只读Proxy对象,需明确定义;context.emit触发父组件事件须先声明emits;context.attrs收集未声明的attribute,可透传;slots通过context.slots或useSlots()使用。

在 Vue 3 的 setup 函数中,父组件传来的属性和事件通信是通过两个固定参数完成的:第一个是 props(接收数据),第二个是 context(提供事件、插槽、非 props 属性等能力)。它们由 Vue 自动注入,不需要手动传入。
props:安全接收并使用父组件传递的属性
props 是一个响应式、只读的 Proxy 对象,包含所有已声明且被父组件传入的 prop。必须先在组件的 props 选项中明确定义,否则值不会出现在 props 对象里,而是落到 context.attrs 中。
- 直接访问推荐:如
props.title、props.count,保持响应性且写法简洁 - 需要解构时务必用
toRefs:避免丢失响应性
import { toRefs } from 'vue'const { title, count } = toRefs(props)→ 模板中可直接写{{ title }},逻辑中读取需title.value - 禁止直接赋值:如
props.count = 10会报错,子组件应通过emit通知父组件修改
context.emit:从子组件向父组件发送事件
子组件要触发自定义事件把数据传回父组件,靠的是 context.emit。它和 Vue 2 的 this.$emit 功能一致,但需提前在组件中用 emits 选项声明允许触发的事件名。
- 父组件绑定:
- 子组件声明:
emits: ['update-name'](不声明也能触发,但会警告,且影响 TypeScript 类型推导) - 子组件调用:
context.emit('update-name', newName),支持多个参数,父组件回调函数会接收到全部
context.attrs:获取未声明的父组件传入属性
当父组件给子组件传了某个 attribute(比如 data-id="123" 或 class="extra"),但子组件没在 props 里声明它,这个值就会自动归入 context.attrs 对象。
- 常用于透传属性(如给根元素加 class、id、aria-* 等)
- 搭配
v-bind="$attrs"可一键透传到子组件内部某个元素上 - 注意:
class和style会自动合并,其他 attribute 默认覆盖
补充:slots 与组合式 API 的配合
父组件通过具名插槽传内容,子组件用 context.slots 接收。在 <script setup></script> 中更常用 useSlots()(需显式引入),但普通 setup() 函数可直接用 context.slots。
- 具名插槽如
xxx,子组件用context.slots.header?.()渲染 - 默认插槽对应
context.slots.default?.() - 插槽函数执行后返回 VNode,需配合
render或模板中的使用











