Utilizziamo i cookie per migliorare la tua esperienza sul sito
CodeWorlds

Fallthrough Attributes

Sygnaly telemetryczne, ktore nie sa zdefiniowane jako props, automatycznie "przenikaja" do glownego elementu komponentu - jak dane z czujnikow do centralnego procesora NOVA LAB. Ten mechanizm nazywa sie fallthrough attributes i jest waznym aspektem tworzenia elastycznych komponentow.

Automatyczne Dziedziczenie

Atrybuty przekazane do komponentu, ktore NIE sa zadeklarowane jako props ani emity, automatycznie trafiaja do root elementu szablonu:

1<!-- Rodzic -->
2<CustomInput class="special" data-testid="email" />
3
4<!-- CustomInput.vue (root = input) -->
5<template>
6  <input type="text" />
7</template>
8
9<!-- Wynik w DOM -->
10<input type="text" class="special" data-testid="email" />

Dotyczy to:

class
,
style
,
id
,
data-*
, event listenerow i innych atrybutow HTML. To zachowanie jest bardzo przydatne - pozwala uzytkownikowi komponentu dodawac klasy CSS, style inline czy atrybuty dostepnosci bez koniecznosci definiowania ich jako props.

Laczenie klas i stylow

Jesli root element komponentu ma juz wlasne

class
lub
style
, Vue automatycznie je laczy (merge) z atrybutami z rodzica:

1<!-- Rodzic -->
2<StatusPanel class="highlighted" style="margin-top: 10px" />
3
4<!-- StatusPanel.vue -->
5<template>
6  <div class="panel" style="padding: 1rem">...</div>
7</template>
8
9<!-- Wynik w DOM - klasy i style polaczone -->
10<div class="panel highlighted" style="padding: 1rem; margin-top: 10px">...</div>

Dziedziczenie event listenerow

Listenery zdarzen rowniez przechodza. Jesli rodzic przekaze

@click
, zostanie on dodany do root elementu:

1<!-- Rodzic -->
2<MarsButton @click="handleClick" />
3
4<!-- MarsButton.vue -->
5<template>
6  <button @click="logInternal">Kliknij</button>
7</template>

W tym przypadku klikniecie przycisku wywoła oba handlery - najpierw

logInternal
z komponentu, potem
handleClick
z rodzica.

Wylaczenie Dziedziczenia

Gdy chcesz kontrolowac dokladnie, gdzie trafiaja atrybuty (np. chcesz je przypisac do wewnetrznego elementu zamiast root), uzyj

inheritAttrs: false
:

1<script setup>
2defineOptions({ inheritAttrs: false })
3</script>
4
5<template>
6  <div class="wrapper">
7    <!-- Reczne przypisanie do konkretnego elementu -->
8    <input v-bind="$attrs" type="text" />
9  </div>
10</template>

To jest czesty wzorzec w komponentach formularzy - wrapper

<div>
sluzy do stylowania, a
$attrs
trafiaja bezposrednio na
<input>
, gdzie sa najbardziej uzyteczne (np.
placeholder
,
disabled
,
aria-label
).

useAttrs()

Dostep do atrybutow w

<script setup>
uzyskujesz przez composable
useAttrs()
:

1<script setup>
2import { useAttrs } from 'vue'
3
4const attrs = useAttrs()
5
6console.log(attrs.class)          // "special"
7console.log(attrs['data-testid']) // "email"
8console.log(attrs.style)         // obiekt stylow
9</script>

Uwaga:

useAttrs()
NIE jest reaktywne - jesli potrzebujesz reagowac na zmiany atrybutow, uzyj
$attrs
bezposrednio w szablonie lub
onUpdated
hook.

Multi-root Components

Gdy komponent ma wiele root elementow (fragments), Vue nie wie, do ktorego przypisac fallthrough attributes. Musisz jawnie przypisac

$attrs
do wybranego elementu:

1<script setup>
2defineOptions({ inheritAttrs: false })
3</script>
4
5<template>
6  <header>Header</header>
7  <main v-bind="$attrs">Content</main>
8  <footer>Footer</footer>
9</template>

Bez

inheritAttrs: false
i jawnego
v-bind="$attrs"
, Vue wyswietli ostrzezenie w konsoli. To wymaga swiadomej decyzji - ktory element ma "dziedziczyc" atrybuty z rodzica.

Praktyczny przyklad - komponent panelu NOVA LAB

Polaczmy wszystkie koncepcje w jednym przykladzie:

1<script setup>
2import { useAttrs } from 'vue'
3
4defineOptions({ inheritAttrs: false })
5
6defineProps({ title: String })
7
8const attrs = useAttrs()
9const hasCustomClass = !!attrs.class
10</script>
11
12<template>
13  <section class="nova-panel">
14    <h3>{{ title }}</h3>
15    <div v-bind="$attrs" class="panel-content">
16      <slot />
17    </div>
18    <small v-if="hasCustomClass">Custom styling applied</small>
19  </section>
20</template>

Dzieki temu wzorcowi rodzic moze przekazac

class
,
style
,
id
i inne atrybuty, ktore trafia dokladnie na
panel-content
, a nie na zewnetrzna
<section>
.

Vai a CodeWorlds