Pebellslearn by building
0%
RoadmapsMatrixCoursesSandboxSign in
Templates  ›  Capstone Project

Attribute Inheritance

Attribute Inheritance 14 minAttributes and listeners a component does not declare as props or emits fall through to its single root element.

Attribute Inheritance

Shelf gets a SearchBox component. On one page the parent writes <SearchBox class="wide" placeholder="Find a book" />. SearchBox never declared class or placeholder as props, yet something happens to them. Knowing where they go saves an afternoon of "why is my input not wide?"

The rule

Undeclared attributes fall through to the single root element.

Anything a parent passes that the child did not claim with defineProps or defineEmits is a fallthrough attribute. That includes class, style, id, placeholder, and v-on listeners such as @click. If the component renders one root element, Vue adds them to it automatically.

<!-- SearchBox.vue, first version -->
<template>
  <label class="search">
    Search
    <input type="search" />
  </label>
</template>

With <SearchBox class="wide" placeholder="Find a book" />, the root label becomes class="search wide" placeholder="Find a book". The class merges nicely with the existing one. The placeholder, sadly, sits on the label, where it does nothing.

To choose the destination yourself, switch off automatic inheritance and bind $attrs where you want it:

<!-- SearchBox.vue, fixed -->
<script setup>
defineOptions({ inheritAttrs: false })
</script>

<template>
  <label class="search">
    Search
    <input type="search" v-bind="$attrs" />
  </label>
</template>

Now placeholder, class and any listener land on the input. In script code the same object is available through useAttrs() from vue.

Several root elements: if a template has more than one top-level element, Vue cannot guess which should receive the attributes. It adds them nowhere and warns, unless you bind $attrs explicitly on one of them.

The shortcut

For every attribute the parent passes, run a three-step check: Declared? Single root? Opted out?

Where does `placeholder` go?Step 1 of 4
  1. Declared?

    Is placeholder a prop or emit of SearchBox? No. So it is a fallthrough attribute.

This is also why declaring emits matters. Listen with @remove on a component that did not declare remove, and the listener falls through to the root element as a native DOM listener instead.

Drills

Answer fast — trust the rule.

quick drill

A single-root component gets id="main-search" from its parent and has no id prop. Where does it go?

quick drill

The root already has class="search" and the parent passes class="wide". What is the result?

quick drill

How do you stop attributes from landing on the root so you can place them yourself?

quick drill

A component has two root elements and does not bind $attrs. What happens to fallthrough attributes?

Remember

  • Attributes and listeners the child does not declare fall through to its single root element.
  • Shortcut: declared? single root? opted out?
  • Trap: an attribute meant for an inner input landing on a wrapper; fix with inheritAttrs: false plus v-bind="$attrs".

Practice — level up

0/1 solved

Write your answer, then compare it with a rubric and a model answer.

ExplainWhere did the class go?

A SearchBox component's template is a <label> wrapping an <input>. The parent writes <SearchBox placeholder="Find a book" class="wide" />. Explain where both attributes land, and how to send the placeholder to the input instead.