透传的情况
- 没有被该组件声明为 props 或者 emits 的attribute,例如class,id等
- v-on绑定的监听器(事件)
第1种透传情况(class,id等):
<!-- <MyButton> 的模板 -->
<button class="btn">click me</button>
// 父组件使用
<MyButton class="large" />
// 透传之后的效果:如果button上面已经有class,它们会进行合并
<button class="large btn">click me</button>
第2种透传情况(v-on监听器)
// 父组件使用
<MyButton @click="onClick" />
// MyButton.vue
// 默认@click="onClick"会添加到根元素上,就是案例中的button
<button>click me</button>
// 如果根节点上有定义的事件事件监听器,那么会触发clickMyself和onClick两个事件
<button @click="clickMyself">click me</button>
禁用 Attributes 继承
有时候我们不想组件的属性透传到组件的根节点上,而是根节点里面的子节点,可以在组件选项中设置 inheritAttrs: false。在vue 3.3开始你也可以直接在 <script setup> 中使用defineOptions。
// 父组件使用
<MyButton class="large" />
// MyButton.vue
<template>
// 没有设置inheritAttrs: false,那么就会渲染成<div class="btn-wrapper large">这样
// 设置inheritAttrs: false,就会保持原状
// 如果子节点想要继承怎么办呢?可以使用v-bind="$attrs"
<div class="btn-wrapper">
<button class="btn" v-bind="$attrs">click me</button>
</div>
</template>
<script setup>
defineOptions({
inheritAttrs: false
})
</script>
多根节点的 Attributes 继承
在vue3中,编写组件不是一定需要一个根节点,所以组件中可以有多个根节点,如果$attrs没有被显式绑定,将会抛出一个运行时警告。
// 父组件使用
<CustomLayout id="custom-layout" @click="changeValue" />
// CustomLayout.vue
<header>...</header>
// 如果没有显式绑定$attrs,会抛出一个警告
<main v-bind="$attrs">...</main>
<footer>...</footer>
在 JavaScript 中访问透传 Attributes
<script setup>
import { useAttrs } from 'vue'
// 可以访问透传的Attributes
const attrs = useAttrs()
</script>