1. Vue3
1.1 .native 修饰符
Vue3 中去掉了 .native 修饰符,默认给子组件的根元素上绑定了监听器。
1.2 emits Option
新增的 emits 允许子组件定义真正被触发的自定义事件。任何没有通过 emits 声明的事件监听器都会被挂载到组件的 $attrs 属性,因此也会被默认绑定到子组件的根节点。
1.3 代码演示
<!-- 父组件 -->
<template>
<Child @click="onClick" />
</template>
<script>
export default {
setup () {
const onClick = (e) => console.log(`target: ${e.target.className};`, `currentTarget: ${e.currentTarget.className};`);
return {
onClick
}
}
}
</script>
<!-- 子组件 -->
<template>
<div class="emit-demo-child">
<div class="div--click" @click="$emit('click', $event)">点击我</div>
</div>
</template>
<script>
export default {
emits: [] // 未声明自定义事件
}
</script>
1.3.1 「现象」一次点击触发两次事件
- 一次来自
$emit()。 - 一次来自子组件根元素的事件监听器。
1.3.2 解决方法
- 如果在子组件的事件处理中包含逻辑,可以在
emits中声明click事件,从而只触发自定义事件。 - 如果在子组件的事件处理中不包含逻辑,可以移除
$emit(),因为子组件的根节点已经默认绑定了事件监听器。
2. Vue2
2.1 v-on 监听
对子组件使用 v-on,只会监听自定义事件(子组件内用 $emit 触发的事件)
2.2 .native 修饰符
- 如果需要监听子组件根元素的原生事件,使用
.native修饰符。 - 子组件中,DOM 元素触发的事件会冒泡到根元素上。
.native有自己的局限性,比如子组件的根节点由input变为label时,像@input.native="xxx"等原生事件就会失效。此时为了兼容性需要做$attr和$listeners的透传。具体参考 Vue2 文档#将原生事件绑定到组件
2.3 代码演示
<!-- 父组件 -->
<template>
<Child @input.native="onInput" />
</template>
<script>
export default {
methods: {
onInput (e) {
console.log(`target: ${e.target.className};`, `currentTarget: ${e.currentTarget.className};`);
}
}
}
</script>
<!-- 子组件 -->
<div class="emit-demo-child">
<input id="input1" />
<input id="input2" />
</div>