Vue est toujours très pratique pour dynamiser des applications ou des composants sur le web. La directive v-if permet de faire apparaître/disparaître un bloc de contenu.
Quand un composant disparaît, avec v-if qui passe à faux (false) lorsqu'on a affaire à un <component :is> qui change de nature composant, Vue le détruit, ses données sont perdues (c'est voulu pour libérer la mémoire), et il repart de zéro si on le fait "revenir".
Lorsqu'on utilise ce principe pour des onglets, cela signifie qu'une saisie commencée dans le premier onglet s'efface dès qu'on consulte le deuxième et ainsi de suite.
👉 Le composant nativement présent dans Vue <KeepAlive> change ce comportement : il met en cache les composants qu'il "enveloppe" au lieu de les détruire.
<script setup>
import { shallowRef } from 'vue'
import OngletIngredients from './OngletIngredients.vue'
import OngletPreparation from './OngletPreparation.vue'
import OngletAvis from './OngletAvis.vue'
// Définition des intitulés des onglets et leur contenu
const onglets = [
{ nom: 'Ingrédients', composant: OngletIngredients },
{ nom: 'Préparation', composant: OngletPreparation },
{ nom: 'Avis', composant: OngletAvis },
]
// Définit l'index de l'onglet actif
const actif = shallowRef (onglets[0])
</script>
<template>
<nav class="onglets">
<button
v-for="onglet in onglets"
:key="onglet.nom"
type="button"
:aria-pressed="actif === onglet"
@click="actif = onglet"
>
{{ onglet.nom }}
</button>
</nav>
<KeepAlive>
<component :is="actif.composant" />
</KeepAlive>
</template>
Dans ce cas de figure si on saisit des informations dans Ingrédients, qu'on passe à Préparation et qu'on revient, les informations vont persister. Sans <KeepAlive>, le champ serait revenu à sa valeur initiale car dans le DOM le formulaire serait totalement retiré puis re-créé. En bonus, c'est plus rapide car le composant n'est pas reconstruit (mais il reste en mémoire donc c'est un peu plus lourd).
<component :is> affiche le composant choisi dynamiquement.
Et <KeepAlive> fonctionne de la même façon autour d'un bloc v-if / v-else. Attention il n'accepte qu'un seul enfant direct à la fois.
Hooks onActivated et onDeactivated
Si on veut réagir à ces opérations pour déclencher d'autres actions en JavaScript, on ne peut plus se servir des hooks onMounted et onUnmounted car un composant en cache n'est ni démonté ni remonté dans le DOM, donc ils ne seront réellement appelés qu'une seule fois, pas à chaque changement d'état. Deux hooks prennent alors le relais :
<script setup>
import { ref, onActivated, onDeactivated } from 'vue'
const portions = ref(4)
onActivated(() => console.log('Ingrédients : affiché'))
onDeactivated(() => console.log('Ingrédients : masqué'))
</script>
<template>
<label for="portions">Nombre de portions</label>
<input id="portions" v-model.number="portions" type="number" min="1">
</template>
Le hook onActivated est appelé au premier affichage et à chaque retour ; onDeactivated à chaque fois que le composant est "mis de côté". C'est là qu'on met en pause ce qui ne doit pas tourner en arrière-plan (une vidéo, un minuteur, un rafraîchissement automatique) et qu'on le relance au retour... ou qu'on rafraîchit des données devenues anciennes.
Choisir ce qui est gardé en cache
L'inconvénient est que chaque composant gardé en cache occupe de la mémoire, avec tout son DOM. Si c'est léger, on peut faire avec. Si le DOM est très lourd, trois props Vue sont prévues pour contrôler plus finement le cache :
<!-- On cache seulement certains composants -->
<KeepAlive :include="['OngletAvis', 'OngletIngredients']">…</KeepAlive>
<!-- On cache tout sauf certains -->
<KeepAlive exclude="OngletPreparation">…</KeepAlive>
<!-- On garde au plus deux composants en cache -->
<KeepAlive :max="2">…</KeepAlive>
- Les props
includeetexcludedésignent les composants par leur nom. Avec la syntaxe<script setup>, le nom est déduit du nom du fichier (OngletAvis.vue→OngletAvis). - La prop
maxlimite le nombre d'instances en cache. Au-delà, la moins récemment utilisée est détruite : avec:max="2", en visitant Ingrédients, puis Préparation, puis Avis, c'est Ingrédients qui sort du cache.
Avec Vue Router
Parmi les cas d'usage les plus répandus, dans une liste de résultats filtrée, on consulte un détail, on revient et la liste a perdu ses filtres et sa position. Avec Vue Router, <RouterView> permet d'accéder au composant de la page courante par son slot et on en profite pour l'envelopper dans un <KeepAlive> :
<template>
<RouterView v-slot="{ Component }">
<KeepAlive>
<component :is="Component" />
</KeepAlive>
</RouterView>
</template>
💡 Combiné avec include, on ne garde que les pages qui le méritent (la liste de résultats, un formulaire long, etc), mais surtout pas toutes les pages visitées sinon le cache grossit à Vue d'oeil ;)
Commenter
Vous devez être inscrit et identifié pour utiliser cette fonction.
Connectez-vous
Pas encore inscrit ? C'est très simple et gratuit.