Vue3深入组件-非 Prop 的 Attribute

前言

一个非 prop 的 attribute 是指传向一个组件,但是该组件并没有相应 props 或 emits 定义的 attribute。常见的示例包括 classstyleid 属性。

Attribute 继承

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
// 父组件
<template>
<div class="no-prop">
<DatePicker
class="no"
data-status="activated"
@change="showChange"
></DatePicker>
</div>
</template>

<script>
import DatePicker from "./DatePicker.vue";

export default {
methods: {
showChange(event) {
console.log(event.target.value); // 将记录所选选项的值
},
},
components: {
DatePicker,
},
};
</script>

// 子组件
<template>
<div class="date-picker">
<input type="datetime" />
<select>
<option value="1">Yesterday</option>
<option value="2">Today</option>
<option value="3">Tomorrow</option>
</select>
</div>
</template>

<script>
export default {
created() {
console.log(this.$attrs); // { onChange: () => {} }
console.log(this.$attrs["data-status"]); // activated
},
};
</script>

注意:渲染的子组件的 dom结构如下

1
2
3
4
<!-- 渲染 date-picker 组件 -->
<div class="date-picker no" data-status="activated">
<input type="datetime" />
</div>

禁用 Attribute 继承

如果你希望组件的根元素继承 attribute,你可以在组件的选项中设置 inheritAttrs: false。例如:

禁用 attribute 继承的常见情况是需要将 attribute 应用于根节点之外的其他元素。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<template>
<div class="date-picker">
<input type="datetime" v-bind="$attrs" />
</div>
</template>

<script>
export default {
inheritAttrs: false,
created() {
console.log(this.$attrs); // { onChange: () => {} }
console.log(this.$attrs["data-status"]); // activated
},
};
</script>

注意:禁用后,data status no 等将应用于 input 元素!

1
2
3
4
<!-- 渲染 date-picker 组件 -->
<div class="date-picker">
<input type="datetime" class="no" data-status="activated" />
</div>

多个根节点上的 Attribute 继承

与单个根节点组件不同,具有多个根节点的组件不具有自动 attribute 回退行为。如果未显式绑定 $attrs,将发出运行时警告。

1
2
3
4
5
6
7
8
// 子组件 改成 多个根节点
<template>
<header></header>
<main v-bind="$attrs">
<input type="datetime" />
</main>
<footer></footer>
</template>

经测试,如未显示绑定 $attrs,未见运行时警告,但dom结构拿不到传进的 data status no