Vue组件自定义事件

组件的自定义事件是一种组件间的通信方式,它适用于子组件向父组件传递数据或行为。vue也有内置一些常用系统事件,例如:鼠标点击,表单提交、滚动事件等等。

组件常用事件

在 Vue 中,常用的事件有以下几种:

  • @click:响应鼠标点击事件;
  • @mouseover:响应鼠标移动到元素上方事件;
  • @keydown:响应键盘按下事件;
  • @submit:响应表单提交事件;
  • @focus:响应元素获得焦点事件;
  • @blur:响应元素失去焦点事件;
  • @change:响应输入框内容变化事件;
  • @scroll:响应元素滚动事件。

使用方法:

  1. 绑定事件:使用 @ 符号加事件名称,例如 @click;
  2. 在 Vue 实例中定义处理事件的方法,例如 onClick;
  3. 在实例中使用 methods 属性,将方法绑定到事件上。

自定义事件

除了以上常用事件,但是大多时候需要我们自己根据业务需要来自定义事件。例如在一个抽屉公共子组件中我们点击了提交@click="submit"按钮,然后在父组件中我们需要针对点击提交后进行业务逻辑处理@submit="handleSubmit"

$emit()

在组件的模板表达式中,可以直接使用 $emit 方法触发自定义事件,例如在子组件child.vue中定义如下

1
2
3
4
5
6
<template>
<div>
<button @click="$emit('emitClick')">$emit触发Click事件</button><br>
</div>
</template>

在父组件中进行引用

1
2
3
4
5
6
7
8
9
10
11
<template>
<div>
<child @emitClick="emitClick"></child>
</div>
</template>

<script setup>
import child from '~/components/Child.vue'
const emitClick = () => { alert('emit方式触发了此事件') }

</script>

defineEmits()

组件可以显式地通过 defineEmits() 宏来声明它要触发的事件,但是我们在 <template> 中使用的 $emit 方法不能在组件的 <script setup> 部分中使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<template>
<div>
<button @click="$emit('emitClick')">$emit触发Click事件</button><br>
<input type="checkbox" @change="handChange">
</div>
</template>


<script setup>
const emits = defineEmits(['parentChange']) // 声明自定义事件
const handChange = () => {
emits('parentChange') // 使用方式和 vue2 this.$emit 一样
}
</script>

在父组件中同样可以调用自定义事件。

1
2
3
4
5
6
7
8
9
10
11
12
<template>
<div>
<child @parentChange="parentChange" @emitClick="emitClick"></child>
</div>
</template>

<script setup>
import child from '~/components/Child.vue'
const parentChange = () => { alert('子组件触发了此事件') }
const emitClick = () => { alert('emit方式触发了此事件') }

</script>

事件参数

有时候我们会需要在触发事件时附带一个特定的值。比如传递一个用户名、头像参数等等。
如下所示我们可以直接在$emit中传递参数,也可以在emits()方法中传递,参数可以是多个。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<template>
<div>
<button @click="handleAdd">点击触发Click事件带参数</button><br>
<button @click="$emit('emitClick',2)">$emit触发Click事件</button><br>
<input type="checkbox" @change="handChange">
</div>
</template>


<script setup>
const emits = defineEmits(['addNum','parentChange']) // 定义自定义事件
const handleAdd = () => {
emits('addNum',1) // 使用方式和 vue2 this.$emit 一样
}
const handChange = () => {
emits('parentChange') // 使用方式和 vue2 this.$emit 一样
}
</script>

父组件可以直接接收子组件传递过来的参数。

1
2
3
4
5
6
7
8
9
10
11
12
13
<template>
<div>
<child @addNum="handleIncreate" @parentChange="parentChange" @emitClick="emitClick"></child>
</div>
</template>

<script setup>
import child from '~/components/Child.vue'
const handleIncreate = (data) => { alert('子组件触发了此事件,传递的值是' + data) }
const parentChange = () => { alert('子组件触发了此事件') }
const emitClick = (data) => { alert('emit方式触发了此事件'+data) }

</script>

参考资料