Cours Vue.js · Module 7: Props et événements
Attributs fallthrough
Dans cette leçon5
Les signaux de télémétrie qui ne sont pas définis comme props « traversent » automatiquement jusqu'à l'élément racine du composant - comme les données des capteurs vers le processeur central du NOVA LAB. Ce mécanisme s'appelle les attributs fallthrough et c'est un aspect important de la création de composants flexibles.
Héritage automatique
Les attributs transmis à un composant qui ne sont PAS déclarés comme props ou emits se retrouvent automatiquement sur l'élément racine du template :
1<!-- Parent -->
2<CustomInput class="special" data-testid="email" />
3
4<!-- CustomInput.vue (racine = input) -->
5<template>
6 <input type="text" />
7</template>
8
9<!-- Résultat dans le DOM -->
10<input type="text" class="special" data-testid="email" />Cela s'applique à : class, style, id, data-*, les écouteurs d'événements et les autres attributs HTML. Ce comportement est très utile - il permet à l'utilisateur du composant d'ajouter des classes CSS, des styles inline ou des attributs d'accessibilité sans avoir à les définir comme props.
Fusion des classes et des styles
Si l'élément racine du composant a déjà sa propre class ou son propre style, Vue les fusionne automatiquement avec les attributs du parent :
1<!-- Parent -->
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<!-- Résultat dans le DOM - classes et styles fusionnés -->
10<div class="panel highlighted" style="padding: 1rem; margin-top: 10px">...</div>Héritage des écouteurs d'événements
Les écouteurs d'événements traversent aussi. Si le parent transmet @click, il sera ajouté à l'élément racine :
1<!-- Parent -->
2<MarsButton @click="handleClick" />
3
4<!-- MarsButton.vue -->
5<template>
6 <button @click="logInternal">Cliquer</button>
7</template>Dans ce cas, cliquer sur le bouton déclenchera les deux gestionnaires - d'abord logInternal du composant, puis handleClick du parent.
Désactiver l'héritage
Quand tu veux contrôler exactement où vont les attributs (par exemple, les assigner à un élément interne plutôt qu'à la racine), utilise inheritAttrs: false :
1<script setup>
2defineOptions({ inheritAttrs: false })
3</script>
4
5<template>
6 <div class="wrapper">
7 <!-- Assignation manuelle à un élément précis -->
8 <input v-bind="$attrs" type="text" />
9 </div>
10</template>C'est un motif courant dans les composants de formulaire - le <div> wrapper sert au style, tandis que $attrs va directement sur l'<input>, là où il est le plus utile (par exemple, placeholder, disabled, aria-label).
useAttrs()
Accède aux attributs dans <script setup> via le 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) // objet style
9</script>Remarque : useAttrs() n'est PAS réactif - si tu dois réagir aux changements d'attributs, utilise $attrs directement dans le template ou le hook onUpdated.
Composants à plusieurs racines
Quand un composant a plusieurs éléments racine (fragments), Vue ne sait pas auquel assigner les attributs fallthrough. Tu dois assigner explicitement $attrs à l'élément choisi :
1<script setup>
2defineOptions({ inheritAttrs: false })
3</script>
4
5<template>
6 <header>Header</header>
7 <main v-bind="$attrs">Contenu</main>
8 <footer>Footer</footer>
9</template>Sans inheritAttrs: false et sans v-bind="$attrs" explicite, Vue affichera un avertissement dans la console. Cela demande une décision consciente - quel élément doit « hériter » des attributs du parent.
Exemple pratique - composant panneau NOVA LAB
Combinons tous les concepts dans un seul exemple :
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">Style personnalisé appliqué</small>
19 </section>
20</template>Grâce à ce motif, le parent peut transmettre class, style, id et d'autres attributs qui vont directement sur panel-content, et non sur la <section> extérieure.
Code de cette leçon : App.vue
1<script setup>
2import CustomInput from './CustomInput.vue'
3import MultiRoot from './MultiRoot.vue'
4</script>
5
6<template>
7 <div class="nova-lab">
8 <h1>Fallthrough Attributes</h1>
9
10 <h2>Héritage automatique :</h2>
11 <CustomInput
12 class="special-input"
13 data-testid="mars-input"
14 placeholder="Type here..."
15 />
16
17 <h2>inheritAttrs: false + manual binding:</h2>
18 <MultiRoot
19 class="highlighted"
20 id="main-section"
21 data-role="content"
22 />
23 </div>
24</template>
25
26<style scoped>
27.nova-lab {
28 background: #0a0e27;
29 color: #00ff88;
30 min-height: 100vh;
31 padding: 20px;
32 font-family: monospace;
33}
34h1 { color: #00ff88; margin-bottom: 20px; }
35h2 { color: #00b4d8; margin: 15px 0 10px; }
36.special-input { border-color: #ff9900 !important; }
37.highlighted { background: rgba(0, 255, 136, 0.15) !important; }
38</style>Tu as repéré une erreur dans cette leçon ?
Teste tes connaissances
Réponds aux questions de cette leçon. Choisis une réponse pour voir tout de suite si elle est correcte.
1. Que sont les attributs fallthrough dans Vue ?
Tâches pratiques dans le jeu
- Tri vertical
Ordonne les étapes pour lier manuellement les attrs :
- Éditeur de code
Désactive inheritAttrs et lie manuellement les attrs à un élément input précis.
- Clique dans l'ordre
Ordonne le code pour accéder aux attrs dans script setup :
- Tri horizontal
Ordonne la liaison manuelle des attrs dans le template :
- Éditeur de code
Crée un composant avec header, main et footer, en assignant $attrs uniquement à main.