组件事件
触发与监听事件
在组件的模板表达式中,可以直接使用$emit()函数触发自定义事件(例如:在v-on
的处理函数中):
<!-- MyComponent --> <button @click="$emit('someEvent ')">click me</button>
父组件可以通过v-on
(缩写为@
)来监听事件:
<MyComponent@some-event ="callback" />
同样,组件的事件监听器也支持.once
修饰符:
<MyComponent@some-event.once ="callback" />
组件与 prop 一样,事件的名字也提供了自动转换。请注意,我们触发了一个以camelCase形式命名的事件,但在父组件中可以使用kebab-case形式来监听。与 prop 大小写格式一样,在模板中我们也推荐使用kebab-case形式来编写监听器。
TIP:和原生 DOM 事件不太一样,组件触发的事件不会冒泡。你只能监听直接子组件触发的事件。
事件参数
有时候我们会需要在触发事件时附带一个特定的值。举个例子,我们想要<BlogPost>
组件来管理文本会缩放得多大。在这个场景下,我们可以给$emit
提供一个值作为额外的参数:
<button @click="$emit('increaseBy ', 1)"> Increase by 1 </button>
然后我们在父组件中监听事件,我们可以先简单写一个内联的箭头函数作为监听器,此时可以访问到事件附带的参数:
<MyButton@increase-by ="(n) => count += n" />
或者用一个方法函数来作为事件处理函数:
<MyButton@increase-by ="increaseCount" />
然后,可以从方法的第一个参数上取到这个值:
//js function increaseCount(n) { count.value += n }
传入$emit()的所有参数都会被直接传向监听器。
template <MyButton@foo ="increase" /> js function increase(n1,n2,n3) { //...... }
MyButton.vue 监听器 foo,将会收到这三个参数值 <button @click="$emit('foo ', 1, 2, 3)"> Increase by 1 </button>
emit()中传值的参数类型,是任意类型,可以是字符串、数字、布尔值、数组、对象等等。
声明触发的事件
组合式 API 中,自定义定义要触发的事件,可以显式地通过defineEmits()宏来声明。
<script setup> constemit = defineEmits(['inFocus', 'submit']) </script>
返回的emit()
函数可以用来在 JavaScript 代码中触发事件。
组合式 API中,即,你没有使用<script setup>
,则事件需要通过emits 选项来定义,emit()
函数也被暴露在setup()
的上下文对象上:
export default { emits: ['inFocus', 'submit'],setup (props, ctx) { ctx.emit('submit') } }
定义触发事件的函数方法,在上两例中展示的字符串类型的数组语法。定义触发事件的函数方法,还支持对象语法,它允许我们对触发事件的参数进行验证:
<script setup> const emit =defineEmits ({ submit(payload) { // 通过返回值为 `true` 还是为 `false` 来判断 验证是否通过 } }) </script>
如果你正在搭配<script setup>
使用TypeScript,也可以使用纯类型标注来声明触发的事件:
<script setuplang="ts" > const emit =defineEmits <{ (e: 'change', id: number): void (e: 'update', value: string): void }>() </script>
更多细节:如何为组件所抛出事件标注类型
尽管是可选的,我们还是推荐你定义所有要触发的事件,以此更好地在代码中描述和呈现组件的作用。这也使得 Vue 能更好地将事件和透传 attribute 作出区分。
如果一个原生事件的名字(例如click
)被定义在 emits 选项中,则监听器只会监听组件触发的click
事件,而不会再响应原生的click
事件。
事件校验
和对prop添加类型校验的方式类似,所有触发的事件也可以使用对象形式来描述。
要为事件添加校验,那么事件可以被赋值为一个函数,接受的参数就是emit()
抛出事件时传入的内容,返回一个布尔值来表明事件是否合法。
<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>