透传 Attributes 的“透传”意味着属性和属性修饰符从一个组件传递到另一个组件,而不需要显式地(通过 defineXXX 声明)在每个组件中重新声明或处理它们,比如 class、style 和 id。
<MyButton class="large" />
-->不需要显式声明直接渲染到DOM上的结果:
<button class="large">Click Me</button>attributes 合并
class 和 style
如果该元素本身具有 class、style 属性,那么透传属性会与之合并,前文已经提及。
v-on 监听器继承
在父组件引入子组件标签上声明一个 v-on:
<MyButton @click="onClick" />事件冒泡
事件处理的顺序是基于事件冒泡机制的。事件首先从目标元素触发,然后冒泡到其父元素,直到到达根元素。因此,如果你在子组件内的某个子元素(例如按钮)上添加了事件监听器,这个监听器会在根元素的监听器之后被触发。 也就是说,一个标签优先响应自身的监听器,然后再逐级响应继承来的监听器。
深层组件继承
父传子的属性,例如 props 或是针对 emits 声明事件的 v-on 侦听函数,经过一层传递即被截留,其余符合要求的 attributes 才会被继续向下传递。 对于 props,如果在一层中没有被 defineProps 声明,会被透传到下一层,emit 事件同理。
禁用继承
该选项控制根组件是否继承父组件的属性:
defineOptions({ inheritAttrs: false })不禁用属性继承的话,本组件中所有声明的 props 都会被应用到根元素上,此时如果在非根元素上想要使用 props 属性,会被根元素截留,因此要禁用自动继承而根据内部标签定义的 props 手动管理继承。
<template>
<button>
<span class="icon" :class="iconClass"></span>
<slot></slot>
</button>
</template>
<script setup>
import { ref } from 'vue'
const iconClass = ref('')
defineOptions({
inheritAttrs: false
})
const disabled = false
</script>还有一种情况,将一些标签放入一个 div 容器中,如果不禁用继承就无法将相应属性传递给子组件。
访问透传属性
$attrs 包括了所有除已声明的 props 和 emits 以外的所有父组件传递的属性。
- 例如
class,style,v-on监听器。
多根节点的 Attributes 继承
首先明确,透传传的其实就是 $attrs 多根节点不会触发自动属性透传,因为不确定把它加到哪个组件上去,此时应当显式声明,否则会触发一个警告:
<header>...</header>
<main v-bind="$attrs">...</main>
<footer>...</footer>在 JS 中访问 Attribute
$attrs 可以直接在 template 中调用,如果要在 script 中访问则需要使用 useAttrs 声明:
<script setup>
import { useAttrs } from 'vue'
const attrs = useAttrs()
console.log(attrs.name)
</script>