在 Vue 3 开发中,组件通信是最基础也是最重要的技能之一。本文将用实际案例演示 Vue 3 中最常用的两种父子通信方式:Props(父传子)和 Emits(子传父),帮助大家快速掌握 Composition API 下的组件通信技巧。
我们有一个父组件 ParentComp
需要向子组件 ChildComp
传递用户信息和主题颜色。
<template>
<div class="parent">
<ChildComp
:user="userData"
:theme="themeColor"
@theme-change="handleThemeChange"
/>
div>
template>
<script setup>
import { ref } from 'vue'
import ChildComp from './ChildComp.vue'
const userData = ref({
name: '张三',
age: 25,
avatar: 'https://example.com/avatar.jpg'
})
const themeColor = ref('blue')
function handleThemeChange(newColor) {
themeColor.value = newColor
}
script>
<template>
<div :class="`user-card ${theme}`">
<img :src="user.avatar" alt="头像">
<h3>{{ user.name }}h3>
<p>年龄: {{ user.age }}p>
<button @click="changeTheme">切换主题button>
div>
template>
<script setup>
// 定义 props 接收父组件数据
const props = defineProps({
user: {
type: Object,
required: true
},
theme: {
type: String,
default: 'light' // 默认值
}
})
// 定义 emits
const emit = defineEmits(['theme-change'])
function changeTheme() {
const newTheme = props.theme === 'blue' ? 'green' : 'blue'
emit('theme-change', newTheme) // 触发事件
}
script>
<style scoped>
.user-card.blue {
border: 2px solid blue;
}
.user-card.green {
border: 2px solid green;
}
style>
defineProps:子组件通过此方法声明接收的 props
props 使用:通过 props.xxx
访问父组件传递的值
子组件需要通知父组件用户点击了"喜欢"按钮,并传递商品ID和喜欢状态。
<template>
<div>
<ProductItem
v-for="product in products"
:key="product.id"
:product="product"
@like="handleLike"
/>
div>
template>
<script setup>
import { ref } from 'vue'
import ProductItem from './ProductItem.vue'
const products = ref([
{ id: 1, name: 'Vue 3教程', price: 99 },
{ id: 2, name: 'TypeScript手册', price: 88 }
])
function handleLike({ id, isLiked }) {
const product = products.value.find(p => p.id === id)
console.log(`${product.name} ${isLiked ? '已点赞' : '取消点赞'}`)
}
script>
<template>
<div class="product">
<h4>{{ product.name }}h4>
<p>价格: {{ product.price }}元p>
<button @click="toggleLike">
{{ isLiked ? '取消喜欢' : '喜欢' }}
button>
div>
template>
<script setup>
import { ref } from 'vue'
const props = defineProps({
product: Object
})
// 定义 emits 并添加验证
const emit = defineEmits({
like: ({ id, isLiked }) => {
if(id && typeof isLiked === 'boolean') {
return true
}
console.warn('无效的 like 事件参数')
return false
}
})
const isLiked = ref(false)
function toggleLike() {
isLiked.value = !isLiked.value
emit('like', {
id: props.product.id,
isLiked: isLiked.value
})
}
script>
defineEmits:子组件通过此方法声明要触发的事件
emit 触发:通过 emit('事件名', 参数)
通知父组件
A: Vue 遵循单向数据流原则,子组件不能直接修改 props。如果需要"修改",应该通过 emit 事件让父组件修改。
A: 不需要!它们是 中的编译器宏,会自动编译为正确的选项。
interface User {
name: string
age: number
}
const props = defineProps<{
user: User
theme?: string // 可选属性
}>()
命名规范:
复杂数据:
性能优化:
通过本文的两个实战案例,相信你已经掌握了 Vue 3 中最核心的父子组件通信方式。记住:
defineProps
defineEmits
在实际开发中,合理运用这些通信方式可以让你的组件更加清晰可维护。如果有任何问题,欢迎在评论区留言讨论!