Q Code

遇事不决 可问春风 春风不语 遵循自心

vue3学习笔记之emit

在vue3中emit的使用方式与vue2有哪些区别?vue3中emit的正确姿势是什么?…

回顾vue2中的emit

在vue2中,子组件想要将自定义事件向上级透传的方式就是this.$emit(<changName>, payload)

child.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<template>
<div>
<button @click="onEmit"> 子组件透传事件 </button>
</div>
</template>
<script>
export default {
methods: {
onEmit() {
this.$emit("on-change", "hi~");
}
}
}
</script>

parent.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<template>
<div>
< child @on-change="onChildChange" />
</div>
</template>
<script>
import Child from "./Child.vue";
export default {
components: {
Child
},
methods: {
onChildChange(v) {
console.log(v); // hi~
}
}
}
</script>

以上就是vue2 中常见的emit使用方式。关键点就是子组件依赖this.$emit透传,父组件使用子组件并v-on指定子组件透传事件Name.

vue3的emit($emit, emits-options)

setup()中的$emit

在setup()的this 是不指向当前实例的(this为undefined),如果想使用使用$emit的功能,需要借助setup(props, context)中的context;

context会暴露三个组件的property;

1
2
3
4
5
6
7
8
9
10
11
12
export default {
setup(props, context) {
// Attribute (非响应式对象)
console.log(context.attrs)

// 插槽 (非响应式对象)
console.log(context.slots)

// 触发事件 (方法)
console.log(context.emit)
}
}

在这里我们需要使用context.emit;如下的🌰

child.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<template>
<div>
<button @click="clickBtn" class="btn-item">hi~</button>
</div>
</template>
<script>
import { defineComponent } from 'vue'
export default defineComponent({
setup (props, ctx) {
const clickBtn = () => {
ctx.emit("on-change", "hi~");
};
return { clickBtn}
}
})
</script>

parent.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<template>
<div>
<emit-child @on-change="emitFn" />
</div>
</template>

<script>
import { defineComponent } from 'vue'
import EmitChild from "./Child.vue"
export default defineComponent({
components: {
EmitChild
},
setup () {
const emitFn = v => {
console.log(v);
}
return { emitFn }
}
})
</script>

效果图:
image

这里说一下如果触发的事件名与原生事件名同名(如 click)会出现问题: 自定义事件与原生事件都会触发
为此将代码略微修改后测试

1
2
3
4
5
6
// child.vue
const clickBtn = () => {
ctx.emit("click", "hi~");
};
// parent.vue
<emit-child @click="emitFn" />

效果图
image
该问题如何解决呢?清往下看

emits-option

详细的文档说明,可以左转链接

在这里简单做一下总结

  1. emits是记录了当前组件的事件列表
  2. 类型: Array | Object
  3. 若为Object增加emit事件的校验(返回值应是boolean),
  4. 可以解决自定义事件名与原生事件相同导致事件多次执行问题(上述)
  5. emits无论是数组或者对象用法最终都会将事件给传递出去,数组或对象的使用只是为了记录实例中的emit事件,或者是验证事件中的参数