Attributes 继承
在此之前,先来弥补一个小知识点,vue3支持多个根节点,vue2不支持,
<!--vue2: 错误的写法-->
<template>
<div></div>
<div></div>
</template>
<!--vue3: 正确-->
<template>
<div></div>
<div></div>
</template>
“透传 attribute”指的是传递给一个组件,却没有被该组件声明为 props 或 emits 的 attribute 或者 v-on 事件监听器。最常见的例子就是 class、style 和 id。
当一个组件以单个元素为根作渲染时,透传的 attribute 会自动被添加到根元素上。举例来说,假如我们有一个 MyButton 组件,它的模板长这样:
<!-- <MyButton> 的模板 -->
<button>click me</button>
一个父组件使用了这个组件,并且传入了 class:
<MyButton class="large" />
最后渲染出的 DOM 结果是:
<button class="large">click me</button>
这里,MyButton 并没有将 class 声明为一个它所接受的 prop,所以 class 被视作透传 attribute,自动透传到了 MyButton的根元素上。
多个根节点
存在多个根节点的时候,并且还传递了透传 attributes,如果没有手动处理的话,是会存在警告的。
那么处理警告的方式两种:
禁用透传 attributes,设置 inheritAttrs 为 false(后面再说)。手动处理,具体绑定在哪一个根节点。
<!--son子组件-->
<template>
<div class="own" :class="$attrs['class']">son组件1</div>
<div class="own">son组件2</div>
</template>
这样警告也会消失,并且把透传 attributes 绑定在了第一个根节点上。这里的$attrs是一个对象,需要具体指明某个属性。
最后渲染的结果
<div class="own abc">son组件1</div>
<div class="own">son组件2</div>
v-on 监听器继承
透传 attributes 之事件绑定 上面只是针对样式进行了透传,那么事件的话,又会是怎么样的呢?
先说结论吧,表现形式跟样式绑定是基本一样的。
<!--子组件Son-->
<script setup lang="ts">
const btn1 = () => {
console.log("子组件的点击事件");
};
</script>
<template>
<button @click="btn1">点击</button>
</template>
现在子组件的根节点是一个 button 标签,并且上面绑定了一个点击事件。
<!--父组件使用-->
<script setup lang="ts">
import Son from "./Son.vue";
const btn = () => {
console.log("父组件的点击事件");
};
</script>
<template>
<Son @click="btn" />
</template>
父组件调用,也传递了一个透传的事件过来。当点击按钮:
现,子组件的事件被触发了,父组件传递过来的事件也被触发了,顺序为先子后父。
透传的 attributes 基本说完了,接下来就看看几个特殊部分吧。
禁用透传attributes
设置 inheritAttrs:false,就禁止使用了自动绑定,可以消除前面所说的警告;然后就可以自由的绑定 $attrs, 该对象就包含了传递过来的透传 attributes。
<!--如果是setup写法,就需要单独添加一个script标签,暴露一个配置对象-->
<script lang="ts">
export default {
inheritAttrs: false, // 禁用
};
</script>
<script setup lang="ts">
const btn1 = () => {
console.log("子组件的点击事件");
};
</script>
<template>
<button @click="btn1">点击</button>
</template>
需要注意的是:
和 props 有所不同,透传 attributes 在 JavaScript 中保留了它们原始的大小写,所以像 foo-bar 这样的一个 attribute 需要通过 $attrs['foo-bar'] 来访问。像 @click 这样的一个 v-on 事件监听器将在此对象下被暴露为一个函数 $attrs.onClick。