Vue3手册译稿 - 深入组件 - 非prop属性
本章节需要要有组件基础
组件的非prop
属性是一个属性或事件传递给组件,但不需要在props
或emits
中进行定义。通常使用的属性包括class
,style
和id
属性。你可以通过$attrs
来访问它们。
属性继承
如果组件只有一个根节点,非prop
属性自动添加到根节点上。例如date-picker
组件实例:
app.component('date-picker', {
template: `
<div class="date-picker">
<input type="datetime-local" />
</div>
`
})
这个事件中我们通过data-status
属性定义一个组件的状态,它会自动加到组件的根节点上(div.date-picker
)
<!-- Date-picker 组件含有非prop属性 -->
<date-picker data-status="activated"></date-picker>
<!-- date-picker组件渲染结果 -->
<div class="date-picker" data-status="activated">
<input type="datetime-local" />
</div>
事件监听规则也是一样:
<date-picker @change="submitChange"></date-picker>
app.component('date-picker', {
created() {
console.log(this.$attrs) // { onChange: () => {} }
}
})
当有一个HTML标签含有change
事件时当作date-picker
组件根点的属性时,非常有用
app.component('date-picker', {
template: `
<select>
<option value="1">Yesterday</option>
<option value="2">Today</option>
<option value="3">Tomorrow</option>
</select>
`
})
在这个例子中,change
事件监听将会从父组件传递到子组件,而且会触发原生<select>
的change
事件。我们不需要再从子件内部将事件监听发射(emit)出来了:
<div id="date-picker" class="demo">
<date-picker @change="showChange"></date-picker>
</div>
const app = Vue.createApp({
methods: {
showChange(event) {
console.log(event.target.value) // 会将选择的值打印到日志中
}
}
})
禁用属性继承
如果你不想让组件属性继承,你可以设置inheritAttrs
:false
选项来禁用它。通用禁用属性继承的场景是除根节点以外的其他元素需要使用该属性。
设置inheritAttrs
为false
后,你可以使用组件的$attrs
属性控制应用到别的元素,包括所有未包含在组件的props
,emits
属性中(如class
,style
,v-on
监听等)。
还是使用前面章节提到的date-picker
组件为例,在这个事件中,我们需要应用所有非prop
属性到input
标签,而不是根节点root
,可以很熟练的使用v-on
快捷方式:
app.component('date-picker', {
inheritAttrs: false,
template: `
<div class="date-picker">
<input type="datetime-local" v-bind="$attrs" />
</div>
`
})
通过这个配置项,data-status
将会被应用到input
标签:
<!-- Date-picker 组件含有非prop属性 -->
<date-picker data-status="activated"></date-picker>
<!-- 渲染 date-picker 组件 -->
<div class="date-picker">
<input type="datetime-local" data-status="activated" />
</div>
多根节点属性继承
不像单根节点组件,多节点组件不能自动将属性挂载,如果$attrs
没有正确配置,运行时当成问题警告:
<custom-layout id="custom-layout" @click="changeValue"></custom-layout>
// 收到告警
app.component('custom-layout', {
template: `
<header>...</header>
<main>...</main>
<footer>...</footer>
`
})
// 不会告警, $attrs 应用到 <main> 标签
app.component('custom-layout', {
template: `
<header>...</header>
<main v-bind="$attrs">...</main>
<footer>...</footer>
`
})