Skip to content

透传 Attribute

如果向组件传递一个属性,但它没有对应 props 或自定义事件,那该属性就是非 props 的 attribute。常见的例子有 id classstyle 属性。

Attribute 继承

如果组件返回单个根节点,非 props 的 attribute 属性将自动应用到根节点上。其中:

  • 传入的 classstyle 值会和根节点已有的值合并。
  • 绑定的事件处理方法也会应用到根节点元素上。
  • 如果根节点已经绑定了对应的事件处理方法,两处都会被触发。
single-root.vue
<template>
<div class="single-root">single-root-component</div>
</template>
<script>
export default {
name: 'SingleRoot',
props: {
attrA: String,
},
};
</script>
demo-attrs.vue
<template>
<single-root
attrA="A"
attrB="B"
id="x"
class="y"
style="color: red;"
@click="childOnClick" />
</template>
<script>
import SingleRoot from './single-root.vue';
export default {
name: 'DemoAttrs',
components: {
SingleRoot,
},
methods: {
childOnClick(event) {
console.log('click target: ', event.target);
// click target: <div class="single-root y" ...
},
},
};
</script>

渲染出的 HTML:

<div
class="single-root y"
attrb="B"
id="x"
style="color: red;">single-root-component</div>

可以看到:

  1. attrA 没有渲染出来,因为它是 props 属性
  2. attrB 渲染为 attrb,因为 HTML 属性名不区分大小写
  3. 传入的 class 属性与根节点的 class 属性合并
  4. 点击事件的目标是子组件的根节点

$attrs

在组件中,可以使用 this.$attrs 访问传入的非 props attribute:

mounted() {
console.log(this.$attrs);
},
/*
{
attrB: "B",
class: "y",
id: "x",
onClick: ƒ (),
style: {
color: 'red'
}
}
*/

禁用继承

可以在组件选项中关闭非 props attribute 的继承:

{
inheritAttrs: false,
}

多根节点组件的处理方式

如果组件返回多个根节点,非 props 的 attribute 将不会自动应用,而且会收到类似下面的警告信息:

[Vue warn]: Extraneous non-props attributes (class) were passed to component but could not be automatically inherited because component renders fragment or text root nodes.

这种情况下,需要手动将 $attrs 绑定到节点:

multiple-root.vue
<template>
<div
class="root-a">root-a</div>
<div
class="root-b"
v-bind="$attrs">root-b</div>
</template>

v-bind="object" 会将一个对象的所有属性都作为 attribute 应用到元素或组件上。