在Vue2.x中v-on指令有.native修饰符,当使用.native修饰符时,会在子组件根元素上加上相应事件监听;去掉.native修饰符时,会触发子组件emit的事件。比如说:
父组件:
<!-- Father.vue -->
<template>
<Child />
</template>
子组件:
<!-- Child.vue -->
<template>
<div class="child">
<div class="inner-child" @click="onClick"></div>
</div>
</template>
<script>
export default {
name: "Child",
method: {
onClick(){
this.$emit("click");
}
}
}
</script>
在Child组件上添加click事件监听<Child @click.native="onClick" />
,实际会在child类上添加一个click事件监听;去掉.native修饰符<Child @click="onClick" />
则接受到的则是子组件onClick方法中emit的click事件。
但是在Vue3中去掉了.native修饰符。那么就有两个问题,如何监听子组件根元素上的事件,以及如何监听子组件根元素上与子组件emit同名的事件(即实现上面例子的@click.native效果)。
在Vue3 RFC30中:Detailed design,有一个新的emits option,用于更详尽的看出这个组件需要向外传递什么样的事件,以及可以用来对emit的参数做校验。emits option同时也会作为setup函数的第二个参数中的一个属性:
setup(props, { emit })
Vue3 RFC31中提到了:v-on Listener Fallthrough。Vue实际上想避免我们使用.native。在Vue3中,在子组件中没有定义emits option的情况下,@click既会监听子组件根元素上的click事件,也会监听子组件中emit的click事件。
- 如果我们只想监听子组件emit的click事件,那需要在子组件中声明该emit:
emit: ["click"]
。此时<Child @click="onClick" />
就只会监听Child emit的click事件。 - 如果我们同时还想监听Child根元素的click事件,则需要去掉子组件中声明的emit。
如果在子组件有同名emit的情况下想单独监听子组件根元素上的同名事件,目前看来无法办到。Vue也在避免我们这样去做。因此在写子组件emit时也要考虑的更加周全。
另外在Vue3 RFC40中:Declaring props and emits,如果我们使用了<script setup>,那么由于defineEmits的类型推断,我们没法emit一个没有事先声明的事件,对于父组件来说就没法同时在子组件根元素上监听同名事件。因此如果有这种特殊需求,不能使用<script setup>。
写得比较绕,可能需要多看几遍。
网友评论