Vue 穿透属性(Fallthrough )

可以使用未声明为 props 的属性来调用组件,这些属性将 穿透fall through) 到组件中的根元素。

使用穿透属性,您可以从创建组件的父级获得更多属性,并且它简化了我们的代码,因为我们不需要将属性声明为 props

用于穿透的典型属性是 class, stylev-on


穿透属性

例如,从父级控制组件样式可能很好,而不是将样式隐藏在组件内部。

让我们创建一个新的例子,Vue 中的基本 todo 列表,看看 style 属性是如何穿透到目标组件的。

So, our App.vue should contain the list of things to do, and an <input> element and a <button> to add new things to do. Each list item is a <todo-item /> component.

因此,我们的 App.vue 应该包含要做的事情的列表,以及一个 <input> 元素和一个 <button> 来添加要做的新事情。每个列表项都是一个 <todo-item /> 组件。

App.vue:

  1. <template>
  2. <h3>Todo List</h3>
  3. <ul>
  4. <todo-item
  5. v-for="x in items"
  6. :key="x"
  7. :item-name="x"
  8. ></todo>
  9. </ul>
  10. <input v-model="newItem">
  11. <button @click="addItem">Add</button>
  12. </template>
  13. <script>
  14. export default {
  15. data() {
  16. return {
  17. newItem: '',
  18. items: ['Buy apples','Make pizza','Mow the lawn']
  19. };
  20. },
  21. methods: {
  22. addItem() {
  23. this.items.push(this.newItem),
  24. this.newItem = '';
  25. }
  26. }
  27. }
  28. </script>

TodoItem.vue 刚刚收到了作为 prop 该做什么的描述:

TodoItem.vue:

  1. <template>
  2. <li>{{ itemName }}</li>
  3. </template>
  4. <script>
  5. export default {
  6. props: ['itemName']
  7. }
  8. </script>

为了正确构建我们的应用程序,我们还需要在 main.js 中进行正确的设置:

main.js:

  1. import { createApp } from 'vue'
  2. import App from './App.vue'
  3. import TodoItem from './components/TodoItem.vue'
  4. const app = createApp(App)
  5. app.component('todo-item', TodoItem)
  6. app.mount('#app')

为了了解本节的要点,即属性可以延伸到组件的 <template> 中的根元素,我们可以从 App.vue 中为列表项提供一些样式:

实例

我们从 App.vue 中为组件内部的 <li> 元素提供样式:

  1. <template>
  2. <h3>Todo List</h3>
  3. <ul>
  4. <todo-item
  5. v-for="x in items"
  6. :key="x"
  7. :item-name="x"
  8. style="background-color: lightgreen;"
  9. />
  10. </ul>
  11. <input v-model="newItem">
  12. <button @click="addItem">Add</button>
  13. </template>

要确认样式属性实际上已经失败,我们可以右键单击浏览器中 todo 列表中的 <li> 元素,选择 'Inspect',我们可以看到样式属性现在位于 <li> 元素上:


合并 'class' 和 'style' 属性

如果已经设置了 'class' 或 'style' 属性,并且 'class' 或 'style' 属性也作为穿透属性来自父级,则这些属性将被合并。

实例

除了来自父级的现有样式外,我们还在 TodoItem.vue 组件内的 <li> 元素中添加了一个边距:

  1. <template>
  2. <li style="margin: 5px 0;">{{ itemName }}</li>
  3. </template>
  4. <script>
  5. export default {
  6. props: ['itemName']
  7. }
  8. </script>

如果我们右键单击浏览器中的 <li> 元素,我们可以看到属性已经合并。边距直接设置在组件内部的 <li> 元素上,并与从父元素穿过的背景颜色合并:


$attrs

如果我们在组件的根级别上有多个元素,那么就不再清楚属性应该属于哪个元素。

为了定义哪一个根元素获得穿透属性,我们可以用内置的 $attrs 对象标记该元素,如下所示:

实例

TodoItem.vue:

  1. <template>
  2. <div class="pinkBall"></div>
  3. <li v-bind="$attrs">{{ itemName }}</li>
  4. <div class="pinkBall"></div>
  5. </template>