「这是我参与2022首次更文挑战的第40天,活动详情查看:2022首次更文挑战」。
我在写关于Vue3新特性系列的文章,今天的主要讲讲在Vue3中新特性中的Fragment和emits。
新特性:Fragment
在Vue2.x中,每个组件只能有一个根,所以在写每个组件模版时都要套父元素。
在Vue3中,引入了Fragment,可以更方便的书写组件模板,支持多根节点组件,也就是片段。
Vue 2.x中语法
Vue 2.x中,不支持多根组件,并且会在用户意外创建多根组件时发出警告。所以,在写代码时,常常会把许多组件被包装在一个<div>中。
<!-- Layout.vue -->
<template>
<div>
<header>...</header>
<main>...</main>
<footer>...</footer>
</div>
</template>
Vue 3语法
Vue 3.x中,组件现在可以有多个根节点。但是,这需要开发人员明确定义属性应该分布在哪里。
<!-- Layout.vue -->
<template>
<header>...</header>
<main v-bind="$attrs">...</main>
<footer>...</footer>
</template>
新特性:emits
vue3针对自定义事件,新增了emits选项。这个选项可以用来定义一个组件可以向其父组件触发的事件。
Vue 2.x语法
Vue2.x中,可以定义一个可接受props的组件,但是无法声明可以出发哪些事件。
<template>
<div>
<p>{{ text }}</p>
<button v-on:click="$emit('accepted')">OK</button>
</div>
</template>
<script>
export default {
props: ['text']
}
</script>
vue 3.x语法
emits和prop类似,但是可以定义组件可出发的事件。emits选项也可以接受一个对象,这个对象允许开发这定义传入事件的参数验证,和props定义的参数验证类似。
<template>
<div>
<p>{{ text }}</p>
<button v-on:click="$emit('accepted')">OK</button>
</div>
</template>
<script>
export default {
props: ['text'],
emits: ['accepted']
}
</script>
在vue3中,强烈建议使用emits记录每个组件所触发的所有事件。因为移除了.native修饰符,任何未在 emits 中声明的事件监听器都会被算入组件的 $attrs,并将默认绑定到组件的根节点上。
对于向父组件传原生事件的组件来说,会导致触发两个事件。示例如下:
<template>
<button v-on:click="$emit('click', $event)">OK</button>
</template>
<script>
export default {
emits: [] // 不声明事件
}
</script>
当一个父级组件拥有 click 事件的监听器时:
<my-button v-on:click="handleClick"></my-button>
该事件会被触发两次:
- 一次来自 $emit()。
- 另一次来自应用在根元素上的原生事件监听器。
总结:如果自定义事件没有写入到emits选项中,当自定义事件名与原生事件名冲突时,事件会被多次触发。所以在vue3中写自定义事件时,都建议将自定义事件写到emits选项中。