web-dev-qa-db-fra.com

Pouvez-vous forcer Vue.js à recharger / re-rendre?

Juste une petite question.

Pouvez-vous forcer Vue.js à tout recharger/recalculer? Si c'est le cas, comment?

153
Dave

Essayez ce sort magique:

vm.$forceUpdate();

Pas besoin de créer de vars suspendus :)

Mise à jour: J'ai trouvé cette solution lorsque je n'ai commencé à travailler qu'avec VueJS. Cependant, une exploration plus poussée a prouvé que cette approche était une béquille. Autant que je me souvienne, je m'en suis débarrassé un jour en plaçant simplement toutes les propriétés qui ne parvenaient pas à s'actualiser automatiquement (principalement celles imbriquées) dans des propriétés calculées.

Plus d'infos ici: https://vuejs.org/v2/guide/computed.html

178
Boris Mossounov

Cela semble être une solution assez propre de matthiasg on ce numéro :

vous pouvez également utiliser :key="someVariableUnderYourControl" et modifier la clé lorsque vous voulez reconstruire complètement le composant

Dans mon cas d'utilisation, je fournissais un getter Vuex à un composant comme accessoire. D'une certaine manière, Vuex récupérait les données mais la réactivité ne déclencherait pas de manière fiable la restitution du composant. Dans mon cas, définir le composant key sur un attribut de l'accessoire garantissait un rafraîchissement lorsque les accesseurs (et l'attribut) étaient finalement résolus.

54
Brian Kung

Pourquoi?

... avez-vous besoin de pour forcer une mise à jour?

Peut-être n’êtes-vous pas en train d’explorer Vue à son meilleur:

Pour que Vue réagisse automatiquement aux modifications de valeur, les objets doivent être initialement déclarée dans data. Sinon, ils doivent être ajoutés à l'aide de Vue.set().

Voir les commentaires dans la démo ci-dessous. Ou ouvrez le même démo dans un JSFiddle ici .

new Vue({
  el: '#app',
  data: {
    person: {
      name: 'Edson'
    }
  },
  methods: {
    changeName() {
      // because name is declared in data, whenever it
      // changes, Vue automatically updates
      this.person.name = 'Arantes';
    },
    changeNickname() {
      // because nickname is NOT declared in data, when it
      // changes, Vue will NOT automatically update
      this.person.nickname = 'Pele';
      // although if anything else updates, this change will be seen
    },
    changeNicknameProperly() {
      // when some property is NOT INITIALLY declared in data, the correct way
      // to add it is using Vue.set or this.$set
      Vue.set(this.person, 'address', '123th avenue.');
      
      // subsequent changes can be done directly now and it will auto update
      this.person.address = '345th avenue.';
    }
  }
})
/* CSS just for the demo, it is not necessary at all! */
span:nth-of-type(1),button:nth-of-type(1) { color: blue; }
span:nth-of-type(2),button:nth-of-type(2) { color: red; }
span:nth-of-type(3),button:nth-of-type(3) { color: green; }
span { font-family: monospace }
<script src="https://unpkg.com/vue"></script>

<div id="app">
  <span>person.name: {{ person.name }}</span><br>
  <span>person.nickname: {{ person.nickname }}</span><br>
  <span>person.address: {{ person.address }}</span><br>
  <br>
  <button @click="changeName">this.person.name = 'Arantes'; (will auto update because `name` was in `data`)</button><br>
  <button @click="changeNickname">this.person.nickname = 'Pele'; (will NOT auto update because `nickname` was not in `data`)</button><br>
  <button @click="changeNicknameProperly">Vue.set(this.person, 'address', '99th st.'); (WILL auto update even though `address` was not in `data`)</button>
  <br>
  <br>
  For more info, read the comments in the code. Or check the docs on <b>Reactivity</b> (link below).
</div>

Pour maîtriser cette partie de Vue, vérifiez la Documents officiels sur Réactivité - Avertissements de détection de changement . C'est à lire absolument!

26
acdcjunior

Utilisez vm.$set('varName', value). Recherchez les détails dans Change_Detection_Caveats .

21
denis.peplin

Bien sûr .. vous pouvez simplement utiliser l'attribut key pour forcer le re-rendu (récréation) à tout moment.

<mycomponent :key="somevalueunderyourcontrol"></mycomponent>

Voir https://jsfiddle.net/mgoetzke/epqy1xgf/ pour un exemple.

Il a également été discuté ici: https://github.com/vuejs/Discussion/issues/356#issuecomment-336060875

13
mgoetzke

Essayez d'utiliser this.$router.go(0); pour recharger manuellement la page en cours.

13
Poy Chang

Veuillez lire ceci http://michaelnthiessen.com/force-re-render/

La façon horrible: recharger la page entière
La manière terrible: utiliser le hack v-if
La meilleure façon: d’utiliser la méthode intégrée forceUpdate de Vue
Le meilleur moyen: changer de clé sur votre composant

<template>
   <component-to-re-render :key="componentKey" />
</template>

<script>
 export default {
  data() {
    return {
      componentKey: 0,
    };
  },
  methods: {
    forceRerender() {
      this.componentKey += 1;  
    }
  }
 }
</script>

J'utilise aussi watch: dans certaines situations.

11
Yash

en utilisant la directive v-if

<div v-if="trulyvalue">
    <component-here />
 </div>

Donc, simplement en changeant la valeur de truevalue de false en true, le composant entre la div sera à nouveau rendu

4
Geoff

J'ai trouvé un moyen. C'est un peu hacky mais ça marche.

vm.$set("x",0);
vm.$delete("x");

vm est votre objet de modèle de vue et x est une variable inexistante.

Vue.js s'en plaindra dans le journal de la console, mais cela déclenchera une actualisation de toutes les données. Testé avec la version 1.0.26.

2
Laszlo the Wiz

Cela a fonctionné pour moi.

created() {
            EventBus.$on('refresh-stores-list', () => {
                this.$forceUpdate();
            });
        },

L'autre composant déclenche l'événement refresh-stores-list provoquera la restitution du composant actuel.

2
sean717

J'avais ce problème avec une galerie d'images que je voulais réémettre en raison de modifications apportées sur un onglet différent. Donc, tab1 = imageGallery, tab2 = favoriteImages

tab @ change = "updateGallery ()" -> ceci force ma directive v-for à traiter la fonction filterImages à chaque fois que je change d'onglet.

<script>
export default {
  data() {
    return {
      currentTab: 0,
      tab: null,
      colorFilter: "",
      colors: ["None", "Beige", "Black"], 
      items: ["Image Gallery", "Favorite Images"]
    };
  },
  methods: {
    filteredImages: function() {
      return this.$store.getters.getImageDatabase.filter(img => {
        if (img.color.match(this.colorFilter)) return true;
      });
    },
    updateGallery: async function() {
      // instance is responsive to changes
      // change is made and forces filteredImages to do its thing
      // async await forces the browser to slow down and allows changes to take effect
      await this.$nextTick(function() {
        this.colorFilter = "Black";
      });

      await this.$nextTick(function() {
        // Doesnt hurt to zero out filters on change
        this.colorFilter = "";
      });
    }
  }
};
</script>
0
Jason

: key = "$ route.params.param1" utilisez simplement la clé avec vos paramètres pour le rechargement automatique des enfants ..

0
Rai Ahmad Fraz

A travaillé pour moi

    data () {
        return {
            userInfo: null,
            offers: null
        }
    },

    watch: {
        '$route'() {
            this.userInfo = null
            this.offers = null
            this.loadUserInfo()
            this.getUserOffers()
        }
    }
0
tuwilof