Appearance
透传 Attributes
Attribute 继承
透传 Attributes 是指父组件传递给子组件的属性,但不被子组件声明为 prop 或 emits 的属性。这些属性会自动传递给子组件的根元素。
html
<MyButton class="large" />html
<!-- <MyButton> 的模板 -->
<button>Click Me</button>最终渲染的结果为
html
<button class="large">Click Me</button>这里MyButton没有将class声明为一个prop,所以class被是为透传 Attributes,自动透传到了MyButton的根元素button上。
对class和style的合并
如果一个子组件的根元素已经有了class或style,那么透传的class或style会被合并到根元素上。
html
<MyButton class="large" />渲染结果为
html
<button class="large large">Click Me</button>v-on监听器继承
同样的合并规则也适用与v-on监听器。
html
<MyButton v-on:click="onClick" />渲染结果为
html
<button v-on:click="onClick">Click Me</button>深层组件继承
有些情况下,一个组件会在根节点上渲染另一个组件,比如我们重构以西啊MyButton,让它在根节点上渲染一个BaseButton
html
<!-- <MyButton/> 的模板,只是渲染另一个组件 -->
<BaseButton />此时 ,MyButton接收的透传 Attributes 会传递给BaseButton。
注意
- 透传的 attribute 不会包含
<MyButton>组件上声明的prop或emits。也就是说,只有当prop或emits没有声明时,透传的 attribute 才会被传递。- 透传的 attribute 若符合声明,也可以作为
props传入<BaseButton>。
禁用 Attribute 继承
有些情况下,你可能不希望组件的根元素继承 attribute。在这种情况下,你可以使用inheritAttrs: false选项。
javascript
// Vue2
export default {
inheritAttrs: false,
props: ['label'],
created() {
console.log(this.$attrs) // 访问非prop属性
}
}
// Vue3.3+
<script setup>
defineOptions({
inheritAttrs: false
})
// ...setup 逻辑
</script>Vue3.2- 结合普通script块
javascript
<script>
export default {
inheritAttrs: false // 传统选项式写法
}
</script>
<script setup>
// 组合式 API 逻辑
</script>Vue3.2- 通过 export default 包装(适合简单场景)
javascript
<script setup>
const __setup__ = {
inheritAttrs: false,
// 其他选项...
}
export default __setup__
</script>最常见的需要禁用透传的场景就是 attribute需要应用在根节点以外的其他元素上.通过设置inherAttrs为false,你可以手动指定哪些 attribute 应该被添加到根节点以外的元素上。
这些透传过来的 attribute 可以通过$attrs对象访问。$attrs是一个响应式对象,包含了除组件所声明的props和emits之外的所有透传的 attribute。你可以使用v-bind指令将$attrs绑定到其他元素上。
html
<ChildComponent v-bind="$attrs" />注意:
- 透传的attribute保留了大小写,需要访问时需要注意(
$attrs['foo-bar']而不是$attrs['fooBar'])- 像
@click这样的监听器事件将会作为$attrs对象的一个函数暴露($attrs.onClick)
html
<div class="btn-wrapper">
<button class="btn" v-bind="$attrs">Click Me</button>
</div>
<script setup>
defineOptions({
inheritAttrs: false,
})
// ...
</script>多根节点的 Attribute 继承
有着多根节点的组件没有自动 attribute 继承行为。如果需要将 attribute 应用到多个根节点上,你可以使用v-bind="$attrs"显式绑定。否则会抛出一个运行时警告
html
<CustomLayout id="custom-layout" @click="changeValue" />html
<!-- CustomLayout.vue -->
<header>...</header>
<main>...</main>
<footer>...</footer>显式绑定
html
<header>...</header>
<main v-bind="$attrs">...</main>
<footer>...</footer>在JavaScript中访问透传 Attributes
html
<script setup>
import { useAttrs } from 'vue'
const attrs = useAttrs()
</script>
<script>
export default {
setup(props, ctx) {
// 透传 attribute 被暴露为 ctx.attrs
console.log(ctx.attrs)
},
}
</script>
<!-- Vue2 -->
<script>
export default {
inheritAttrs: false,
created() {
console.log(this.$attrs) // 访问非prop属性
},
}
</script>注意: 在没有使用
<script setup>的情况下,虽然attrs对象总是反映为最新的透传 attribute,,但它不是响应式的,不可以通过侦听器去监听他的变化, 如果需要响应性,可以使用prop或者可也可以使用onUpdated()使每次更新的时候结合最新的attrs执行副作用