Vue3基础知识-setup()参数:props和context
一、完整代码实现
我们将实现一个简单的功能:父组件 App
向子组件 Student
传递 name
和 age
属性,子组件通过按钮触发自定义事件,向父组件传递参数并弹窗显示。
1.1 子组件:Student.vue
<template><h1>name:{{name}}</h1><h1>age:{{age}}</h1><button @click="setMsg">测试自定义事件</button>
</template><script>
export default {name: "Student",props:["name","age"],emits:['getMsg'],//声明其自定义事件,不加会警告。Vue2无需添加/*知识点1:setup()参数:props和contextprops:声明接受的参数context:attrs:接受参数。若组件没用props:["name","age"]收参,attrs会进行接收。相当于Vue2中的$attrsemit:触发自定义事件。相当于Vue2中的$emitslots:收到插槽内容。相当于Vue2中的$slots(建议使用v-slot命名)*/setup(props,context){function setMsg(){context.emit("getMsg",123)}return{setMsg}}
}
</script><style scoped></style>
1.2 父组件:App.vue
<template><student @getMsg="getMsg" name="zhangsan" age="18" />
</template><script>import Student from "@/components/Student";export default {name: 'App',components: {Student},setup(){function getMsg(val){alert(`自定义事件触发,接收到参数:${val}`)}return{getMsg}}
}
</script><style></style>
二、核心知识点解析
2.1 setup 函数的两个核心参数
setup
函数是 Vue3 Composition API 的 “入口”,接收两个固定参数:props
和 context
。
(1)props:接收父组件传递的属性
- 特性:
props
是响应式对象,会随父组件传递的值变化而自动更新。 - 注意点:
- 必须在组件的
props
选项中显式声明要接收的属性(如props: ["name", "age"]
)。 - 不能直接解构
props
(如const { name } = props
),会破坏其响应式特性(若需解构,需用toRefs
工具函数,例:const { name } = toRefs(props)
)。
- 必须在组件的
- 示例:在
Student
组件中,可直接通过props.name
、props.age
访问父组件传递的值。
(2)context:上下文对象(非响应式)
context
是一个普通对象(非响应式,可安全解构),包含 3 个核心属性,对应 Vue2 中的 $attrs
、$emit
、$slots
:
属性名 | 作用 | Vue2 对应 API | 示例 |
---|---|---|---|
attrs | 接收父组件传递但未在 props 中声明的属性 | this.$attrs | 若父传 gender="male" 但未在 props 声明,可通过 context.attrs.gender 获取 |
emit | 触发自定义事件,向父组件传递数据 | this.$emit | context.emit("事件名", 参数) |
slots | 接收父组件传递的插槽内容 | this.$slots | 若父组件用 <template #default> 传内容,可通过 context.slots.default() 获取 |
重点:
context.emit
是子组件向父组件通信的核心方法,必须配合emits
选项声明事件(Vue3 规范)。
2.2 自定义事件的 “声明 - 触发 - 监听” 流程
Vue3 中自定义事件的使用更强调 “规范”,必须经过以下 3 步,否则控制台会出现警告:
步骤 1:子组件声明自定义事件(emits 选项)
在子组件的 export default
中,通过 emits: ["事件名"]
声明要触发的自定义事件(如 emits: ["getMsg"]
)。
- 作用:明确告知 Vue 该组件会触发哪些事件,避免与原生事件冲突,同时提升代码可读性。
步骤 2:子组件触发自定义事件(context.emit)
在子组件的逻辑中(如按钮点击事件),通过 context.emit("事件名", 参数)
触发事件并传递数据。
示例:context.emit("getMsg", 123)
表示触发 getMsg
事件,并向父组件传递参数 123
。
步骤 3:父组件监听自定义事件
在父组件使用子组件的标签上,通过 @事件名="回调函数"
监听子组件的自定义事件,并在回调函数中接收参数。
示例:<Student @getMsg="getMsg" />
,其中 getMsg
函数的参数就是子组件传递的 123
。