Vue3 自定义事件
Vue3 自定义事件
- 1.快速入门
- 1.1 示例
- 1.2 详细说明
- 2. 事件参数(不限个数)
- 3. 事件校验
1.快速入门
1.1 示例
通过上一章 《Vue3 Props》,我们知道组件中的 prop 遵循单向数据流原则,即父组件可以直接修改 prop 值,而子组件无法直接修改 prop 或者父组件的数据。
但是,我们又希望子组件能够和父组件进行通信,所以就有了自定义事件,简单说,就是子组件通过自定义一个事件,通知父组件,让父组件在外部进行处理。
比如,我们以一个电子木鱼组件为例

Counter.vue:
<template><h2 class="title">电子木鱼</h2><div><button @click="$emit('addCount')">我今天敲了{{ counter }}下木鱼</button></div>
</template><script setup>
const props = defineProps({counter: {typeof: Number,default: 0}
})
const emit = defineEmits(['addCount'])</script><style lang="scss" scoped>
</style>
App.vue:
<template><div><Counter :counter="counter" @add-count="addCount"/></div>
</template><script setup>
import Counter from '@/components/Counter.vue'
import { ref } from 'vue'const counter = ref(10)
function addCount() {counter.value++
}
</script><style lang="scss" scoped></style>

1.2 详细说明
(1)子组件通过$emit(事件名)向外部触发(发射)自定义事件。比如:
<button @click="$emit('addCount')">我今天敲了{{ counter }}下木鱼</button>
(2)子组件的自定义事件需要 defineEmits 进行显式声明,否则无法使用。比如:
const emit = defineEmits(['addCount'])
(3)父组件监听子组件自定义事件,和普通事件一样,@加上事件名即可进行定义。比如:
<Counter :counter="counter" @add-count="addCount"/>
(4)事实上,父组件监听子组件事件名时,可以使用 camelCase(小驼峰) 形式命名,但是和 prop 一样,官方也推荐 kebab-case 形式来编写监听器。
2. 事件参数(不限个数)
有时候,我们希望子组件的自定义事件可以携带参数(不限个数),可以放在事件名的后面。
比如,我希望我敲木鱼的速度是别人的10倍。关键代码如下:
子组件:
<button @click="$emit('addCount', 10)">我今天敲了{{ counter }}下木鱼</button>
父组件:
function addCount(step) {counter.value = counter.value + step
}

注意:所有传入
$emit()的额外参数都会被直接传向监听器。举例来说,$emit('foo', 1, 2, 3)触发后,监听器函数将会收到这三个参数值。
3. 事件校验
和对 props 添加类型校验的方式类似,所有触发的事件也可以使用对象形式来描述。
看个示例。

我们希望自定义每次敲木鱼增加的实际次数,但是又不希望增加的次数为非整数。
对 Counter.vue 进行改造:
<template><h2 class="title">电子木鱼</h2><div><input type="number" v-model="step" placeholder="请输入倍数"><button @click="$emit('addCount', step)">我今天敲了{{ counter }}下木鱼</button></div>
</template><script setup>
import { ref } from 'vue';const step = ref(1)
const props = defineProps({counter: {typeof: Number,default: 0},
})
const emit = defineEmits({// 校验 addCount 事件addCount: (step) => {if(step % 1 === 0) {return true} else {console.warn('请输入整数的倍数')return false}}
})</script><style lang="scss" scoped>
button{margin-left: 10px;
}
</style>
点击6次,没有问题。

当我们修改倍数为 2.5 倍时,就会校验不通过,从而产生警告。但是只是警告,父组件还是监听并执行了该事件。

上一章 《Vue3 Props》
