Skip to content

Fallthrough atributy

Tato stránka předpokládá, že už jste četli Základy komponent. Pokud jsou pro vás komponenty nové, přečtěte si je jako první.

Dědičnost attributů

Fallthrough atribut je atribut nebo v-on event listener, který je předáván do komponenty, ale není explicitně deklarován ve vlastnostech (props) nebo emitovaných událostech (emits) cílové komponenty. Typickými příklady jsou atributy class, style, a id.

Když komponenta vykresluje jediný root element, budou k atributům root elementu automaticky přidány fallthrough atributy. Například pro komponentu <MyButton> s následující šablonou:

template
<!-- šablona pro <MyButton> -->
<button>klikni na mě</button>

A s rodičem užívajícím komponentu takto:

template
<MyButton class="large" />

Bude ve výsledku vykreslený DOM vypadat:

html
<button class="large">klikni na mě</button>

V tomto případě <MyButton> nedeklarovala class jako svou vlastnost. Proto je class zpracována jako fallthrough attribut a automaticky přidána do root elementu komponenty <MyButton>.

Spojování class a style

Pokud root element komponenty potomka již obsahuje existující atributy class nebo style, budou sloučeny s hodnotami class a style, které jsou předávány z rodiče. Předpokládejme, že změníme šablonu <MyButton> z předchozího příkladu na:

template
<!-- šablona pro <MyButton> -->
<button class="btn">klikni na mě</button>

Pak se vykreslený DOM změní na:

html
<button class="btn large">klikni na mě</button>

Dědičnost v-on listenerů

Stejné pravidlo se uplatní na v-on event listenery:

template
<MyButton @click="onClick" />

Listener click bude přidán do root elementu <MyButton>, tj. do nativního prvku <button>. Když se klikne na nativní <button>, vyvolá to metodu onClick komponenty rodiče. Pokud nativní <button> již listener click vázaný přes v-on má, pak budou vyvolány oba.

Dědičnost vnořených komponent

Pokud komponenta ve svém root elementu vykresluje jinou komponentu, například pokud jsme upravili <MyButton> tak, aby jako svůj root vykreslovala <BaseButton>:

template
<!-- šalona <MyButton/>, která jednoduše vykreslí jinou komponentu -->
<BaseButton />

Tak budou fallthrough atributy obdržené v <MyButton> automaticky přesměrovány do <BaseButton>.

Zapamatujte si, že:

  1. Přesměrované atributy nezahrnují žádné atributy, které jsou v <MyButton> deklarovány jako vlastnosti nebo v-on listenery deklarovaných událostí - jinými slovy, deklarované vlastnosti a listenery byly „spotřebovány“ uvnitř <MyButton>.

  2. Přesměrované atributy mohou být akceptovány jako vlastnosti <BaseButton>, pokud tam jsou deklarovány.

Zamezení dědičnosti atributů

Pokud nechcete, aby komponenta automaticky dědila atributy, můžete v jejím nastavení zadat inheritAttrs: false.

Od Vue 3.3 můžete použít defineOptions i přímo uvnitř <script setup>:

vue
<script setup>
defineOptions({
  inheritAttrs: false
})
// ...setup logika
</script>

Běžným důvodem pro zakázání dědičnosti atributů je situace, kdy je třeba atributy použít i na jiné elementy než na root. Nastavením inheritAttrs na false můžete mít plnou kontrolu nad tím, kde mají být fallthrough atributy použity.

K těmto fallthrough atributům lze přistoupit přímo ve výrazech šablon přes $attrs:

template
<span>Fallthrough attributy: {{ $attrs }}</span>

Objekt $attrs obsahuje všechny atributy, které nejsou deklarovány jako props nebo emits komponenty (např., class, style, v-on listenery, atd.).

Pár poznámek:

  • Na rozdíl od vlastností zachovávají falltrough atributy i v JavaScriptu původní podobu klíče, takže k atributu foo-bar je třeba přistupovat jako $attrs['foo-bar'] a nikoli $attrs['fooBar'].

  • Event listener v-on jako @click bude v objektu zpřístupněn jako funkce $attrs.onClick.

Při použití naši ukázkové <MyButton> komponenty z předchozí sekce můžeme někdy potřebovat obalit element <button> do extra <div> tagu pro účely stylování:

template
<div class="btn-wrapper">
  <button class="btn">klikni na mě</button>
</div>

Chceme, aby všechny falltrough atributy jako class nebo v-on listener byly aplikovány na vnitřní <button> a nikoli vnější <div>. Toho můžeme docílit s inheritAttrs: falsev-bind="$attrs":

template
<div class="btn-wrapper">
  <button class="btn" v-bind="$attrs">klikni na mě</button>
</div>

Pamatujte, že v-bind bez parametrů naváže na cílový element všechny vlastnosti objektu jako atributy.

Dědičnost atributů na více root elementech

Na rozdíl od komponent s jediným root elementem nemají komponenty s více root elementy automatické chování pro fallthrough atributy. Pokud není proveden explicitní binding $attrs, vyvolá to za běhu varování.

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

Pokud má <CustomLayout> následující multi-root šablonu, objeví se varování, protože Vue si nemůže být jisté, jak má fallthrough attributy správně aplikovat:

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

Varování bude potlačeno, pokud je proveden explicitní binding $attrs:

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

Přistupování k falltrough atributům v JavaScriptu

Pokud je třeba, lze k falltrough atributům komponenty přistoupit uvnitř <script setup> pomocí useAttrs() API:

vue
<script setup>
import { useAttrs } from 'vue'

const attrs = useAttrs()
</script>

Pokud nepoužíváte <script setup>, attrs budou vystaveny jako vlastnost kontextu setup():

js
export default {
  setup(props, ctx) {
    // fallthrough attributy jsou vystaveny jako ctx.attrs
    console.log(ctx.attrs)
  }
}

Všimněte si, že ačkoli zde objekt attrs vždy odráží nejnovější fallthrough atributy, není reaktivní (z výkonnostních důvodů). Ke sledování jeho změn nelze použít watchers. Pokud potřebujete reaktivitu, použijte vlastnost (prop). Alternativně můžete použít onUpdated(), abyste při každé aktualizaci komponenty provedli vedlejší efekty s nejnovějšími attrs.

Pokud je třeba, lze k falltrough atributům komponenty přistoupit přes instanční proměnnou $attrs:

js
export default {
  created() {
    console.log(this.$attrs)
  }
}
Fallthrough atributy has loaded