自定义事件
自定义事件的核心思想,子组件传递数据给父组件。
另外,父组件传递给子组件的数据,子组件不能去改,此时子组件也可以通过自定义事件的形式,去通知父组件,让父组件即时的更新数据。
快速上手
这里以评分组件为例:
vue
<template>
<div class="rating-container">
<span v-for="star in 5" :key="star" class="star" @click="setStar(star)">
{{ rating >= star ? '★' : '☆' }}
</span>
</div>
</template>
<script setup>
import { ref } from 'vue'
const rating = ref(0) // 表示几颗星
const emits = defineEmits(['update-rating'])
function setStar(newStar) {
rating.value = newStar
// 我们需要将最新的星星状态的值传递给父组件
// 触发父组件的 update-rating 事件
emits('update-rating', rating.value)
}
</script>
<style scoped>
.rating-container {
display: flex;
font-size: 24px;
cursor: pointer;
}
.star {
margin-right: 5px;
color: gold;
}
.star:hover {
color: orange;
}
</style>
在上面的评分组件中,我们需要将子组件 rating 的状态值传递给父组件,通过触发父组件所绑定的 update-rating 事件来进行传递。
vue
<template>
<div class="app-container">
<h1>请对本次服务评分:</h1>
<Rating @update-rating="handleRating" />
<p v-if="rating > 0">你当前的评价为 {{ rating }} 颗星</p>
</div>
</template>
<script setup>
import { ref } from 'vue'
import Rating from './components/Rating.vue'
const rating = ref(0)
function handleRating(newRating) {
// 更新父组件的数据就可以了
rating.value = newRating
}
</script>
<style scoped>
.app-container {
max-width: 600px;
margin: auto;
text-align: center;
font-family: Arial, sans-serif;
}
p {
font-size: 18px;
color: #333;
}
</style>
父组件在使用子组件的时候,就为子组件绑定了自定义事件,本例中是 update-rating 事件,当子组件触发该事件时,就会执行该事件所对应的事件处理函数 handleRating. 事件处理函数的形参就能够接收到子组件传递过来的数据。
事件相关细节
模板中使用$emit()触发事件
在组件的模板中,可以直接使用 $emit 去触发自定义事件。例如上面的评分的组件例子,可以这么写:
vue
<span v-for="star in 5" :key="star" class="star" @click="$emit('update-rating', star)">
{{ rating >= star ? '★' : '☆' }}
</span>
和前面所介绍的 Props 类似,自定义事件也是支持校验的。这里的校验主要是对子组件要传递给父组件的值进行校验。
emit校验
要添加校验,需要书写为对象的形式,对象的键是事件名,值是校验函数,校验函数所接收的参数就是 emit 触发事件时要传递给父组件的参数,需要返回一个布尔值来说明传递的值是否通过了校验。
vue
<script setup>
const emit = defineEmits({
// 没有校验
click: null,
// 校验 submit 事件
submit: ({ email, password }) => {
if (email && password) {
return true
} else {
console.warn('Invalid submit event payload!')
return false
}
}
})
function submitForm(email, password) {
emit('submit', { email, password })
}
</script>
例如还是拿刚才的评分组件来举例:
js
defineProps(['rating'])
const emits = defineEmits({
'update-rating': (value) => {
if (value < 1 || value > 5) {
console.warn('传递的值有问题!!!')
return false
}
return true
}
})
function setStar(newStar) {
// 我们需要将最新的星星状态的值传递给父组件
// 触发父组件的 update-rating 事件
emits('update-rating', 100)
}
-EOF-