在 Vue 中,组件通信的核心机制之一是 props 和 事件(emit)。Vue2 和 Vue3 在接收 props 和触发/监听事件的方式上有一些语法上的差异,特别是在组合式 API 的引入后。
一、Vue2 接收 Props 并触发事件
1. 定义 Props
export default { props: ['title', 'count'] }
也可以定义类型校验:
props: { title: String, count: Number }
2. 使用 Props
<template> <div>{{ title }}, {{ count }}</div> </template>
3. 触发事件(子组件)
this.$emit('updateCount', this.count + 1)
4. 监听事件(父组件)
<ChildComponent :count="currentCount" @update-count="handleUpdateCount" />
二、Vue3 Options API 接收 Props 并触发事件
1. 定义 Props
export default {
props: ['title', 'count'],
setup(props, { emit }) { // 可以使用 props.title 等 } }
支持类型校验:
props: { title: String, count: Number }
2. 使用 Props
<template> <div>{{ title }}, {{ count }}</div> </template>
3. 触发事件(子组件)
const emit = defineEmits(['updateCount']) emit('updateCount', count.value + 1)
或者使用 setup(props, { emit })
的方式:
setup(props, { emit }) { emit('updateCount', props.count + 1) }
4. 监听事件(父组件)
<ChildComponent :count="currentCount" @update-count="handleUpdateCount" />
三、Vue3 Composition API(<script setup>
)接收 Props 并触发事件
1. 定义 Props
<script setup> import { defineProps } from 'vue'
const props = defineProps(['title', 'count']) </script>
带类型校验:
defineProps({ title: String, count: Number })
2. 使用 Props
<template> <div>{{ props.title }}, {{ props.count }}</div> </template>
3. 触发事件(子组件)
<script setup>
import { defineEmits } from 'vue'
const emit = defineEmits(['updateCount'])
function increment() {
emit('updateCount', props.count + 1)
}
</script>
4. 监听事件(父组件)
<template>
<ChildComponent :count="currentCount" @update-count="handleUpdateCount" />
</template>
四、Vue3 <script setup>
新特性:defineModel
(Vue3.4+)
适用于双向绑定场景,如 v-model
:
子组件
<script setup> const model = defineModel() </script> <template> <input v-model="model" /> </template>
父组件
<ChildComponent v-model="message" />
等价于:
<ChildComponent :modelValue="message" @update:model-value="val => message = val" />
五、总结对比表
功能 | Vue2 | Vue3 Options API | Vue3 <script setup> |
---|---|---|---|
定义 props | props: [...] | props: [...] 或 defineProps() | defineProps() |
获取 props 值 | this.title | props.title | props.title |
触发事件 | this.$emit('event') | emit('event') | defineEmits() / emit() |
监听事件(父组件) | @event="handler" | @event="handler" | @event="handler" |
支持 defineModel | ❌ | ❌ | ✅(Vue3.4+) |
六、最佳实践建议
- ✅ 对于 Vue3 新项目,推荐使用
<script setup>
和defineProps
/defineEmits
- ✅ 复杂组件建议显式声明 props 类型和事件
- ✅ 使用
defineModel
简化v-model
场景 - ✅ 避免直接修改 props,应通过
$emit
或事件通知父组件更新 - ✅ 组件间通信尽量保持单向数据流原则
💡 注意:Vue3 中不再推荐使用
.sync
修饰符,建议用显式的props + emit
替代。