Salut les experts,

J'ai un problème qui me fait juste "peter un cable" depuis 3 jours.

Je fais une appli web en VueJS avec plusieurs pages, en réalité il s'agit plus d'un site que d'une appli.

La page d'accueil charge une liste d'items récupérés via un fetch au moment de l'étape CREATED du cycle de vie.
La liste est insérée dans une variable "items" présente dans l'objet retourné par "data()".
Ensuite, je parcours cette variable dans le template pour afficher chaque item.

Plus précisement :

  • [CREATED] ---> je récupère la liste des items au près du backend-end et je met à jour la variable "items";
  • [UPDATED] ---> la mise à jour de la variable "items" à déclenché l'évenement UPDATED, j'en profite pour faire autre chose sur la liste insérée;

Quand la page est chargée via un appel direct de l'URL par le navigateur, ou via un clic dans la navigation, tout fonctionne bien, par contre quand je passe par un retour de page (history back), UPDATED n'est pas déclenché.

Côté router, je n'utilise pas celui de Vue, il ne me convient pas.
J'ai donc fait un petit router perso qui affiche un composant ou l'autre en fonction de l'URL.
Voici la base de son code, la fonction "Handler" permet de changer de composant.

<main>
    <div id="router-root">
        <template v-if="currentComponent === 'Home'">
            <Home :updater="updater" @handler="Handler"/>
        </template>
        <template v-if="currentComponent === 'Item'">
            <Item :updater="updater"/>
        </template>
        <template v-if="currentComponent === 'Error'">
            <Error />
        </template>
    </div>
</main>

Et voici le code du composant Home (épuré)

<script lang="ts">

export default {
    created() {

        console.log('--- [CREATED] ---');
        // ==> JE CHARGE LA LISTE DES ITEMS, this.items est mise à jour

    },
    mounted() {

        console.log('--- [MOUNTED] ---');
        // ==> JE FAIS RIEN DE SPECIAL

    },
    updated() {

        console.log('--- [UPDATED] ---');
        // ==> LA LISTE DES ITEMS EST CHARGÉE DANS LE HTML, JE DOIS FAIRE DES ACTIONS SUR CETTE LISTE POUR GERER UN INFINITE SCROLL

    },
    data() {
        return {
            items: [] as Array<any>,
        }
    }
};

</script>

<template>
    <div v-for="item of items">
        <!-- Affiche l'item -->
    </div>
</template>

Ce que je veux

Que UPDATED soit appelé dans tous les cas de figure, quelqu'en soit l'origine du chargement de la page.
Il faut que je vois le console.log('--- [UPDATED] ---');

Ce que j'obtiens

UPDATED n'est pas appelé dans le cas d'un retour de page (history back, évenement "popstate").
Je vois bien console.log('--- [CREATED] ---') et console.log('--- [MOUNTED] ---'), mais pas
console.log('--- [UPDATED] ---');

Avez-vous une idée de la raison du problème ?
Est-ce que Vue, et plus globalement les framework JS ont des limitations par rapport au retour de page ?

En vous remerciant par avance pour vos lumières.

1 réponse


<script lang="ts">
export default {
created() {
console.log('--- [CREATED] ---');
// ==> JE CHARGE LA LISTE DES ITEMS, this.items est mise à jour
this.loadItems();
},
mounted() {
console.log('--- [MOUNTED] ---');
// ==> JE FAIS RIEN DE SPECIAL
},
updated() {
console.log('--- [UPDATED] ---');
// ==> LA LISTE DES ITEMS EST CHARGÉE DANS LE HTML, JE DOIS FAIRE DES ACTIONS SUR CETTE LISTE POUR GERER UN INFINITE SCROLL
},
data() {
return {
items: [] as Array<any>,
};
},
methods: {
loadItems() {
// Ici, vous chargez la liste des items depuis votre source de données (API, base de données, etc.)
// Une fois que la liste est chargée, vous pouvez appeler la méthode updated() manuellement pour déclencher son exécution.
this.$nextTick(() => {
this.updated();
});
},
},
mounted() {
window.addEventListener('popstate', this.onPopState);
},
beforeDestroy() {
window.removeEventListener('popstate', this.onPopState);
},
methods: {
onPopState(event) {
// Lorsque l'événement "popstate" est déclenché, vous appelez la méthode loadItems() pour mettre à jour la liste des items et forcer l'appel de updated().
this.loadItems();
},
},
};
</script>