Vue 透传属性
一个组件可以被调用带有未声明为 props 的属性,这些属性会简单地透传到组件中的根元素。
使用透传属性可以从创建组件的父组件获得更好的概述,并且它简化了我们的代码,因为我们不需要将属性声明为 props。
常用的透传属性包括 class
、style
和 v-on
。
透传属性
例如,从父组件控制组件的样式而不是将样式隐藏在组件内部可能很方便。
让我们创建一个新的示例,一个基本的 Vue 待办事项列表,并看看 style 属性如何透传到代表待办事项的组件。
所以,我们的 App.vue
应该包含待办事项列表,以及一个 <input>
元素和一个 <button>
用于添加新的待办事项。每个列表项都是一个 <todo-item />
组件。
App.vue
:
<template>
<h3>Todo List</h3>
<ul>
<todo-item
v-for="x in items"
:key="x"
:item-name="x"
/>
</ul>
<input v-model="newItem">
<button @click="addItem">Add</button>
</template>
<script>
export default {
data() {
return {
newItem: '',
items: ['Buy apples','Make pizza','Mow the lawn']
};
},
methods: {
addItem() {
this.items.push(this.newItem),
this.newItem = '';
}
}
}
</script>
而 TodoItem.vue
只接收待办事项的描述作为属性
TodoItem.vue
:
<template>
<li>{{ itemName }}</li>
</template>
<script>
export default {
props: ['itemName']
}
</script>
为了正确构建我们的应用程序,我们还需要在 main.js
中进行正确的设置
main.js
:
import { createApp } from 'vue'
import App from './App.vue'
import TodoItem from './components/TodoItem.vue'
const app = createApp(App)
app.component('todo-item', TodoItem)
app.mount('#app')
为了说明本节的重点,即属性可以透传到我们组件 <template>
内部的根元素,我们可以从 App.vue
为列表项设置一些样式
示例
我们从 App.vue
为组件内部的 <li>
元素设置样式
<template>
<h3>Todo List</h3>
<ul>
<todo-item
v-for="x in items"
:key="x"
:item-name="x"
style="background-color: lightgreen;"
/>
</ul>
<input v-model="newItem">
<button @click="addItem">Add</button>
</template>
运行示例 »
为了确认 style 属性确实已经透传,我们可以在浏览器中右键单击待办事项列表中的一个 <li>
元素,选择“检查”,我们就可以看到 style 属性现在位于 <li>
元素上了。
合并 'class' 和 'style' 属性
如果 'class' 或 'style' 属性已经设置,并且 'class' 或 'style' 属性也作为透传属性从父组件传递过来,则这些属性将被合并。
示例
除了来自父组件的现有样式外,我们还向 TodoItem.vue
组件内部的 <li>
元素添加一个边距
<template>
<li style="margin: 5px 0;">{{ itemName }}</li>
</template>
<script>
export default {
props: ['itemName']
}
</script>
运行示例 »
如果我们右键单击浏览器中的一个 <li>
元素,我们可以看到属性已经合并。边距直接设置在组件内部的 <li>
元素上,并与从父组件透传的背景颜色合并。
$attrs
如果我们在组件的根级别有多个元素,就不再清楚应该将属性透传到哪个元素。
为了定义哪个根元素获取透传属性,我们可以使用内置的 $attrs
对象标记该元素,如下所示
示例
TodoItem.vue
:
<template>
<div class="pinkBall"></div>
<li v-bind="$attrs">{{ itemName }}</li>
<div class="pinkBall"></div>
</template>
运行示例 »