Puoi forzare Vue.js a ricaricare / ripetere il rendering?


231

Solo una domanda veloce.

Puoi forzare Vue.jsa ricaricare / ricalcolare tutto? Se é cosi, come?


Potrebbe ottenere un supporto migliore qui github.com/vuejs/Discussion/issues
Cory Danielson,

Fantastico, non sapevo di quel luogo di discussione. Ci proverò laggiù.
Dave,

Hai finito per ottenere una risposta? Mi piacerebbe sapere anche.
Oddman,

Non ricordare esattamente. Ma ecco il problema che ho aperto con alcuni indizi: github.com/vuejs/Discussion/issues/356
Dave,

Ho una direttiva v-for nella vista e ho un caso d'uso quando cambio manualmente due oggetti su quell'array. Vue non esegue automaticamente il rendering del modello dopo questo. Ho usato una soluzione alternativa: basta fare qualsiasi azione con questo array (spingere oggetto vuoto e quindi giuntare) - questo innesca il rendering. Ma questo è un caso speciale.
Fyodor Khruschov,

Risposte:


237

Prova questo incantesimo:

vm.$forceUpdate();

Non è necessario creare alcun vaso sospeso :)

Aggiornamento: ho trovato questa soluzione quando ho iniziato a lavorare solo con VueJS. Tuttavia, ulteriori esplorazioni hanno dimostrato questo approccio come una stampella. Per quanto ricordo, in un attimo mi sono sbarazzato di esso semplicemente mettendo tutte le proprietà che non sono riuscite ad aggiornarsi automaticamente (principalmente quelle nidificate) in proprietà calcolate.

Maggiori informazioni qui: https://vuejs.org/v2/guide/computed.html


4
questo mi ha davvero aiutato quando lo stavo usando con un componente di procedura guidata per moduli in Vue. I campi dei campi del mio modulo stavano perdendo stato sebbene le variabili di dati fossero intatte. Ora sto usando questo per aggiornare le viste quando torno, ho dovuto metterlo nella funzione setTimeout.
Jimmy Ilenloa,

26
Si noti che nei file vue è necessario 'this. $ ForceUpdate ();'
Katinka Hesselink,

1
Funziona benissimo per l'aggiornamento di una lunga chiamata axios.
AlfredBr

4
In qualche modo assolutamente strano, $forceUpdate()mai e poi mai lavorato per me il 2.5.17.
Abana Clara,

2
@AbanaClara $ forceUpdate () non è mai stato un metodo pubblico, l'ho trovato scavando il codice sorgente di Vue. E poiché il suo utilizzo non è mai stato il modo giusto di Vue'ing, forse potrebbe essere rimosso. Non posso dire con certezza se è ancora lì, dal momento che non faccio più front-end.
Boris Mossounov,

82

Questa sembra una soluzione abbastanza pulita di matthiasg su questo problema :

è inoltre possibile utilizzare :key="someVariableUnderYourControl"e modificare la chiave quando si desidera ricostruire completamente il componente

Per il mio caso d'uso, stavo alimentando un getter Vuex in un componente come supporto. In qualche modo Vuex avrebbe recuperato i dati ma la reattività non si sarebbe avviata in modo affidabile per eseguire nuovamente il rendering del componente. Nel mio caso, l'impostazione del componente keysu un attributo sull'elica ha garantito un aggiornamento quando i getter (e l'attributo) si sono finalmente risolti.


1
Questo è un piccolo trucco pulito, fondamentalmente forza una ri-istanziazione del componente ( mountedverrà eseguito, ecc.)
btk

1
@btk Sono d'accordo, probabilmente non è il modo "giusto" di fare le cose, ma è un trucco abbastanza pulito, per quello che è.
Brian Kung,

1
questo utile. Uso il percorso completo del percorso come chiave per rendere nuovamente lo stesso componente quando il percorso cambia. : key = "$ route.fullPath"
Nirav Gandhi

44

Perché?

... si ha bisogno di forzare un aggiornamento?

Forse non stai esplorando Vue al meglio:

Affinché Vue reagisca automaticamente alle variazioni di valore, gli oggetti devono essere inizialmente dichiarati indata . Oppure, in caso contrario, devono essere aggiunti utilizzandoVue.set() .

Vedi i commenti nella demo qui sotto. O apri la stessa demo in un JSFiddle qui .

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>

Per padroneggiare questa parte di Vue, controlla la documentazione ufficiale sulla reattività - Avvertenze sul rilevamento delle modifiche . È assolutamente da leggere!


2
Sicuramente d'accordo sul fatto che dovresti mettere in discussione questo requisito di aggiornamento, ma a volte devi solo riutilizzare l'interfaccia utente perché il viewport è cambiato e devi mostrare risorse diverse (come un esempio). I dati potrebbero non essere stati effettivamente modificati.
the_dude_abides,

1
Perché è necessario ricaricare? In alcuni casi i file di risorse (fogli di stile / js) memorizzati nella cache dal browser devono essere ricaricati dopo un certo periodo di tempo. Avevo un foglio di stile che doveva essere ricaricato dopo 7 giorni e se un utente teneva aperta una scheda con un accesso alla pagina e tornava dopo 7 giorni per navigare in quella pagina, il CSS aveva più di 7 giorni.
Aurovrata,

@AchielVolckaert probabilmente hai già trovato la risposta, ma sì, Vue.set()funziona anche all'interno dei componenti.
acdcjunior,

1
@the_dude_abides e @ Aurovrata, questi sono usi legittimi di aggiornamento, sono d'accordo. L'interrogazione che ho posto è che le persone non raramente fanno il rinfrescante per le ragioni sbagliate.
acdcjunior,

1
Forse stai solo cercando di correggere un bug in un'app Web mal progettata che utilizza Vue esclusivamente come strumento di rendering e, ad esempio, ricarica l'intera applicazione ogni volta che va sul server, ignorando le funzionalità dell'applicazione lato client di Vue. Nel mondo reale, non hai sempre il tempo di correggere ogni abominio che trovi.
Warren Dew il

30

Si prega di leggere questo http://michaelnthiessen.com/force-re-render/

Il modo orribile: ricaricare l'intera pagina
Il modo terribile: usare l'hack v-if
Il modo migliore: usare il metodo forceUpdate integrato di Vue
Il modo migliore: cambiare chiave sul tuo componente

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

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

Uso anche watch: in alcune situazioni.


Assolutamente, sono d'accordo con te!
Diamante

Ho quasi rinunciato a Vue. Ma grazie a questo, la mia fiducia in Vue è stata ripristinata.
jokab,

Il link in realtà non mostra come farlo in modo orribile, che è purtroppo ciò di cui ho bisogno poiché la mia app è progettata per navigare in modo orribile. Un semplice URL della pagina corrente non sembra funzionare, almeno non nell'app che sto trattando, quindi ho davvero bisogno di istruzioni su come farlo in modo orribile.
Warren Dew il

@WarrenDew Si prega di seguire: stackoverflow.com/questions/3715047/...
Yash

25

Prova a utilizzare this.$router.go(0);per ricaricare manualmente la pagina corrente.


3
Più semplice: questo. $ Router.go ()
Marius,

In realtà @MariusAndreiana - la funzione .go () richiede 1 parametro non opzionale
a_lovelace



12
<my-component :key="uniqueKey" />

insieme ad esso usa this.$set(obj,'obj_key',value) e aggiorna uniqueKeyper ogni aggiornamento nel valore oggetto (obj) per ogni aggiornamentothis.uniqueKey++

ha funzionato per me in questo modo


6

Quindi ci sono due modi per farlo,

1). È possibile utilizzare $forceUpdate()all'interno del gestore del metodo, ad es

<your-component @click="reRender()"></your-component>

<script>
export default {
   methods: {
     reRender(){
        this.$forceUpdate()
     }
   }
}
</script>

2). È possibile assegnare un :keyattributo al componente e aumentare quando si desidera eseguire nuovamente il rendering

<your-component :key="index" @click="reRender()"></your-component>

<script>
export default {
   data() {
     return {
        index: 1
     }
   },
   methods: {
     reRender(){
        this.index++
     }
   }
}
</script>

5

usando la direttiva v-if

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

Quindi, semplicemente cambiando il valore di truevalue da false a true, il componente tra il div verrà nuovamente renderizzato


1
Secondo me questo è il modo più pulito per ricaricare i componenti. Anche nel metodo Created () È possibile aggiungere alcuni elementi di inizializzazione.
Piotr Żak,

5

Per ricaricare / ri-renderizzare / aggiornare il componente, interrompere le codifiche lunghe. C'è un modo Vue.JS per farlo.

Usa solo l' :keyattributo.

Per esempio:

<my-component :key="unique" />

Sto usando quello nello slot della tabella BS Vue. Dicendo che farò qualcosa per questo componente in modo da renderlo unico.


3

Questo ha funzionato per me.

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

L'altro componente genera l'evento refresh-stores-list causerà il rendering del componente corrente


2

Ho trovato un modo. È un po 'confuso ma funziona.

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

Dov'è vml'oggetto del modello di visualizzazione ex è una variabile inesistente.

Vue.js si lamenterà di ciò nel registro della console ma avvia un aggiornamento per tutti i dati. Testato con la versione 1.0.26.


2

Ha funzionato per me

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

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


0

: key = "$ route.params.param1" usa semplicemente key con i tuoi parametri per ricaricare automaticamente i figli ..


4
prova a fornire informazioni dettagliate sulla tua soluzione. aggiungi il tuo codice, evidenzia le parole chiave
Agilanbu

0

Ho avuto questo problema con una galleria di immagini che volevo renderizzare a causa delle modifiche apportate in una scheda diversa. Quindi tab1 = imageGallery, tab2 = favoriteImages

tab @ change = "updateGallery ()" -> questo impone alla mia direttiva v-for di elaborare la funzione filteredImages ogni volta che cambio scheda.

<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

scusate ragazzi, tranne il metodo di ricarica della pagina (sfarfallio), nessuno di loro funziona per me (: la chiave non ha funzionato).

e ho trovato questo metodo dal vecchio forum vue.js che funziona per me:

https://github.com/vuejs/Discussion/issues/356

<template>
    <div v-if="show">
       <button @click="rerender">re-render</button>
    </div>
</template>
<script>
    export default {
        data(){
            return {show:true}
        },
        methods:{
            rerender(){
                this.show = false
                this.$nextTick(() => {
                    this.show = true
                    console.log('re-render start')
                    this.$nextTick(() => {
                        console.log('re-render end')
                    })
                })
            }
        }
    }
</script>
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.