Przejdź bezpośrednio do treści

Dziedziczone atrybuty

Ta strona zakłada, że przeczytałeś już Podstawy komponentów. Przeczytaj to najpierw, jeśli dopiero zaczynasz pracę z komponentami.

Dziedziczenie atrybutów

"Dziedziczony atrybut" to atrybut lub nasłuchujący zdarzenia v-on, który jest przekazywany do komponentu, ale nie jest jawnie zadeklarowany we właściwościach (props) lub zdarzeniach emitowanych komponentu odbierającego. Typowe przykłady to atrybuty class, style i id.

Gdy komponent renderuje pojedynczy element główny, dziedziczone atrybuty zostaną automatycznie dodane do atrybutów elementu głównego. Na przykład, mając komponent <MyButton> z następującym szablonem:

template
<!-- szablon <MyButton> -->
<button>Wciśnij mnie</button>

A rodzic używający tego komponentu z:

template
<MyButton class="large" />

Finalny wyrenderowany DOM będzie:

html
<button class="large">Wciśnij mnie</button>

Tutaj, <MyButton> nie zadeklarował class jako akceptowanego prop. W związku z tym, class jest traktowany jako przechodzący atrybut i automatycznie dodawany do głównego elementu <MyButton>.

Łączenie class i style

Jeśli główny element komponentu potomnego ma już istniejące atrybuty class lub style, zostaną one połączone z wartościami class i style odziedziczonymi po rodzicu. Załóżmy, że zmienimy szablon <MyButton> w poprzednim przykładzie na:

template
<!-- template of <MyButton> -->
<button class="btn">Wciśnij mnie</button>

Wtedy finalny wyrenderowany DOM stanie się:

html
<button class="btn large">Wciśnij mnie</button>

Dziedziczenie nasłuchiwania v-on

Ta sama zasada dotyczy nasłuchiwania zdarzeń v-on:

template
<MyButton @click="onClick" />

Nasłuchiwanie click zostanie dodane do głównego elementu <MyButton>, tj. natywnego elementu <button>. Gdy natywny <button> zostanie kliknięty, wywoła metodę onClick komponentu rodzica. Jeśli natywny <button> ma już nasłuchiwanie click powiązane z v-on, wtedy oba nasłuchiwania zostaną wywołane.

Dziedziczenie komponentów zagnieżdżonych

Jeśli komponent renderuje inny komponent jako swój główny węzeł, na przykład, przebudowaliśmy <MyButton> aby renderował <BaseButton> jako swój główny element:

template
<!-- szablon <MyButton/> który po prostu renderuje inny komponent -->
<BaseButton />

Wtedy przechodzące atrybuty otrzymane przez <MyButton> zostaną automatycznie przekazane do <BaseButton>.

Należy zauważyć, że:

  1. Przekazywane atrybuty nie zawierają żadnych atrybutów, które są zadeklarowane jako props lub nasłuchiwania v-on zdarzeń zadeklarowanych przez <MyButton> - innymi słowy, zadeklarowane props i nasłuchiwania zostały "skonsumowane" przez <MyButton>.

  2. Przekazywane atrybuty mogą być akceptowane jako props przez <BaseButton>, jeśli zostały przez niego zadeklarowane.

Wyłączanie dziedziczenia atrybutów

Jeśli nie chcesz, aby komponent automatycznie dziedziczył atrybuty, możesz ustawić inheritAttrs: false w opcjach komponentu.

Od wersji 3.3 możesz również użyć defineOptions bezpośrednio w <script setup>:

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

Częstym scenariuszem wyłączenia dziedziczenia atrybutów jest sytuacja, gdy atrybuty muszą być zastosowane do innych elementów niż główny węzeł. Ustawiając opcję inheritAttrs na false, możesz przejąć pełną kontrolę nad tym, gdzie przechodzące atrybuty powinny być zastosowane.

Te przechodzące atrybuty mogą być dostępne bezpośrednio w wyrażeniach szablonu jako $attrs:

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

Obiekt $attrs zawiera wszystkie atrybuty, które nie zostały zadeklarowane przez opcje props lub emits komponentu (np. class, style, nasłuchiwanie v-on, itp.).

Kilka uwag:

  • W przeciwieństwie do props, przechodzące atrybuty zachowują swoją oryginalną pisownię w JavaScript, więc do atrybutu takiego jak foo-bar trzeba się odwoływać jako $attrs['foo-bar'].

  • Nasłuchiwanie zdarzenia v-on jak @click będzie dostępne w obiekcie jako funkcja pod $attrs.onClick.

Używając naszego przykładu komponentu <MyButton> z poprzedniej sekcji - czasami może być konieczne owinięcie właściwego elementu <button> dodatkowym <div> dla celów stylizacji:

template
<div class="btn-wrapper">
  <button class="btn">Wciśnij mnie</button>
</div>

Chcemy, aby wszystkie przechodzące atrybuty jak class i nasłuchiwanie v-on były zastosowane do wewnętrznego <button>, a nie zewnętrznego <div>. Możemy to osiągnąć za pomocą inheritAttrs: false i v-bind="$attrs":

template
<div class="btn-wrapper">
  <button class="btn" v-bind="$attrs">Wciśnij mnie</button>
</div>

Pamiętaj, że v-bind bez argumentu wiąże wszystkie właściwości obiektu jako atrybuty elementu docelowego.

Dziedziczenie atrybutów na wielu głównych węzłach

W przeciwieństwie do komponentów z pojedynczym głównym węzłem, komponenty z wieloma głównymi węzłami nie mają automatycznego zachowania przechodzenia atrybutów. Jeśli $attrs nie są jawnie powiązane, zostanie wyświetlone ostrzeżenie w czasie wykonywania.

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

Jeśli <CustomLayout> ma następujący szablon z wieloma głównymi węzłami, pojawi się ostrzeżenie, ponieważ Vue nie może być pewne, gdzie zastosować przechodzące atrybuty:

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

Ostrzeżenie zostanie wyciszone, jeśli $attrs zostanie jawnie powiązane:

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

Dostęp do przechodzących atrybutów w JavaScript

Jeśli potrzebne, możesz uzyskać dostęp do przechodzących atrybutów komponentu w <script setup> używając API useAttrs():

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

const attrs = useAttrs()
</script>

Jeśli nie używasz <script setup>, attrs będzie dostępne jako właściwość kontekstu setup():

js
export default {
  setup(props, ctx) {
    // fallthrough attributes are exposed as ctx.attrs
    console.log(ctx.attrs)
  }
}

Zauważ, że chociaż obiekt attrs zawsze odzwierciedla najnowsze przechodzące atrybuty, nie jest reaktywny (ze względów wydajnościowych). Nie możesz użyć obserwatorów do śledzenia jego zmian. Jeśli potrzebujesz reaktywności, użyj prop. Alternatywnie, możesz użyć onUpdated() aby wykonać efekty uboczne z najnowszymi attrs przy każdej aktualizacji.

Jeśli potrzebne, możesz uzyskać dostęp do przechodzących atrybutów komponentu przez właściwość instancji $attrs:

js
export default {
  created() {
    console.log(this.$attrs)
  }
}
Dziedziczone atrybutyJest załadowany