Luna Tech

Tutorials For Dummies.

Vue: Fallthrough Attributes

2022-03-27


0. Intro

Fallthrough Attributes | Vue.js (vuejs.org)

What is a Fallthrough Attribute?

“fallthrough attribute” 是一个 attribute 或者一个 v-on event listener,它会被 pass to a component,但是它没有明确地在 receiving component 的 props 或者 emits 里面去定义。

Examples


1. Attribute Inheritance

当 component 渲染一个 single root element 的时候,fallthrough attribute 会自动被加入到 root element 的 attribute 里面。

Example

Child

<!-- template of <MyButton> -->
<button>click me</button>

Parent

<MyButton class="large" />

Final rendered DOM - attribute from parent is inherited

<button class="large">click me</button>

class and style merging

假如 child compinent 的 root element 已经存在 classstyle attribute 了,那么它会与从 parent 继承来的 classstyle value 合并。

Example

Child:

<!-- template of <MyButton> -->
<button class="btn">click me</button>

Parent:

<MyButton class="large" />

Final Rendered DOM:

<button class="btn large">click me</button>

v-on listener inheritance

同样地,v-on event listener 的规则是:

Example

Parent:

<MyButton @click="onClick" />

这个 click listener 会被加到 MyButton (child) 的 root element 上,也就是加到 native button element 上。

当 native button 被点击时,它会触发 onClick method of the parent component. 假如 native <button> 已经有一个与 v-on 绑定的 click listener,那么两个 listener 都会被触发(类似 class 和 style 的merge)。

Nested Component Inheritance

当一个 component 把另一个 component 渲染为它的 root node,比如我们把 MyButton 重构为 render BaseButton as root,而不是直接 render button html:

<!-- template of <MyButton/> that simply renders another component -->
<BaseButton />

这种情况下, MyButton 接收到的 fallthrough attribute 就会自动被 forward 给 BaseButton

Note

  1. Forwarded attributes do not include any attributes that are declared as props, or v-on listeners of declared events by <MyButton> - in other words, the declared props and listeners have been “consumed” by <MyButton>.
  2. Forwarded attributes may be accepted as props by <BaseButton>, if declared by it.
  1. Forwarded attributes 不包括被 MyButton 用掉的 props 和 listener。
  2. Forwarded attribute 可能被 BaseButton 作为 props 接收(假如 BaseButton 有声明)。

2. Disabling Attribute Inheritance

假如你不想自动继承的话,可以通过 inheritAttrs: false in the component’s options 来 disable 这个功能。

常用情况

假如 attributes 需要被除了 root node 之外的其他 element 使用的话,我们常常会 set to false,这样就可以 take full control of where the fallthrough attributes should be applied.

如何 access fallthrough attributes?

可以用 $attrs 来获取以及直接在 template 里面使用。

The $attrs object includes all attributes that are not declared by the component’s props or emits options (e.g., class, style, v-on listeners, etc.).

<span>Fallthrough attributes: {{ $attrs }}</span>

Notes

有时候需要 wrap extra div for styling purposes

<div class="btn-wrapper">
  <button class="btn">click me</button>
</div>

如果想要 apply fallthrough attribute to inner element 怎么办?

假如我们不想让 div 去 inherit,而是让 button 去 inherit,就要用 inheritAttrs: false and v-bind="$attrs"

不带 argument 的v-bind会把 object 所有的 properties 都绑定为 target element 的 attributes。

<div class="btn-wrapper">
  <button class="btn" v-bind="$attrs">click me</button>
</div>

Remember that v-bind without an argument binds all the properties of an object as attributes of the target element.


3. Attribute Inheritance on Multiple Root Nodes

假如一个 component 有多个 root node,那么就自动丧失 fallthrough behavior。如果我们没有明确地绑定 $attrs,就会看到一个 runtime warning message。

Example

<CustomLayout id="custom-layout" @click="changeValue" />

If <CustomLayout> has the following multi-root template, there will be a warning because Vue cannot be sure where to apply the fallthrough attributes.

<header>...</header>
<main>...</main>
<footer>...</footer>

Fix - explicitly bind $attrs

<header>...</header>
<main v-bind="$attrs">...</main>
<footer>...</footer>

4. Accessing Fallthrough Attributes in JavaScript

如果需要的话,你也可以直接在 JS 里面通过 $attrs 去 access 这些 fallthrough attributes。

export default {
  created() {
    console.log(this.$attrs)
  }
}