Können Sie Vue.js zwingen, neu zu laden / neu zu rendern?

230

Nur eine kurze Frage.

Können Sie zwingen Vue.js, alles neu zu laden / neu zu berechnen ? Wenn das so ist, wie?

Dave
quelle
Könnte hier bessere Unterstützung bekommen github.com/vuejs/Discussion/issues
Cory Danielson
Großartig, wusste nichts über diesen Diskussionsort. Ich werde es dort versuchen.
Dave
Hast du eine Antwort bekommen? Ich bin auch gespannt darauf.
Oddman
Ich erinnere mich nicht genau. Aber hier ist das Problem, das ich mit einigen Hinweisen eröffnet habe: github.com/vuejs/Discussion/issues/356
Dave
Ich habe eine v-for-Direktive in der Ansicht und einen Anwendungsfall, wenn ich zwei Objekte in diesem Array manuell austausche. Vue rendert die Vorlage danach nicht automatisch neu. Ich habe eine Problemumgehung verwendet: Führen Sie einfach eine Aktion mit diesem Array aus (drücken Sie ein leeres Objekt und spleißen Sie dann) - dies löst ein erneutes Rendern aus. Dies ist jedoch ein Sonderfall.
Fyodor Khruschov

Antworten:

236

Versuchen Sie diesen Zauber:

vm.$forceUpdate();

Keine Notwendigkeit, hängende Vars zu erstellen :)

Update: Ich habe diese Lösung gefunden, als ich erst mit VueJS angefangen habe. Weitere Untersuchungen haben diesen Ansatz jedoch als Krücke bewiesen. Soweit ich mich erinnere, habe ich es nach einer Weile losgeworden, einfach alle Eigenschaften, die nicht automatisch aktualisiert wurden (meistens verschachtelte), in berechnete Eigenschaften zu setzen.

Weitere Informationen hier: https://vuejs.org/v2/guide/computed.html

Boris Mossounov
quelle
4
Dies hat mir sehr geholfen, als ich es mit einer Komponente des Formularassistenten in Vue verwendet habe. Meine Formularfelder Felder verloren den Status, obwohl die Datenvariablen intakt waren. Jetzt verwende ich dies, um die Ansichten zu aktualisieren, wenn ich zurückgehe. Ich musste sie in die Funktion setTimeout einfügen.
Jimmy Ilenloa
26
Beachten Sie, dass Sie in vue-Dateien 'this. $ ForceUpdate ();' benötigen.
Katinka Hesselink
1
Dies eignet sich hervorragend zum Aktualisieren eines nach einem längeren Axios-Aufrufs.
AlfredBr
4
Auf eine absolut seltsame Art und Weise $forceUpdate()hat NIEMALS am 2.5.17 für mich gearbeitet.
Abana Clara
2
@AbanaClara $ forceUpdate () war nie eine öffentliche Methode, ich fand es, den Quellcode von Vue zu graben. Und da seine Verwendung nie die richtige Art des Vue'ing war, könnte es vielleicht entfernt werden. Kann nicht sicher sagen, ob es noch da ist, da ich kein Frontend mehr mache.
Boris Mossounov
82

Dies scheint eine ziemlich saubere Lösung von matthiasg zu diesem Thema zu sein :

Sie können :key="someVariableUnderYourControl"den Schlüssel auch verwenden und ändern, wenn die Komponente vollständig neu erstellt werden soll

Für meinen Anwendungsfall habe ich einen Vuex-Getter als Requisite in eine Komponente eingespeist. Irgendwie würde Vuex die Daten abrufen, aber die Reaktivität würde nicht zuverlässig eintreten, um die Komponente neu zu rendern. In meinem Fall keygarantierte das Setzen der Komponente auf ein Attribut auf der Requisite eine Aktualisierung, wenn die Getter (und das Attribut) endgültig aufgelöst wurden.

Brian Kung
quelle
1
Dies ist ein hübscher kleiner Trick, der im Grunde genommen eine Neuinstanziierung der Komponente erzwingt ( mountedwird ausgeführt usw.)
btk
1
@btk Ich stimme zu, es ist wahrscheinlich nicht die "richtige" Art, Dinge zu tun, aber es ist ein ziemlich sauberer Hack für das, was es ist.
Brian Kung
1
das ist hilfreich. Ich verwende den vollständigen Pfad der Route als Schlüssel, um dieselbe Komponente erneut zu rendern, wenn sich die Route ändert. : key = "$ route.fullPath"
Nirav Gandhi
44

Warum?

... tun Sie brauchen , um eine Aktualisierung zu erzwingen?

Vielleicht erkunden Sie Vue nicht von seiner besten Seite:

Damit Vue automatisch auf Wertänderungen reagiert, müssen die Objekte zunächst in deklariert werdendata . Wenn nicht, müssen sie mit hinzugefügt werdenVue.set() .

Siehe Kommentare in der Demo unten. Oder öffnen Sie hier dieselbe Demo in einer JSFiddle .

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>

Um diesen Teil von Vue zu beherrschen, lesen Sie die offiziellen Dokumente zu Reaktivität - Änderungserkennungsvorbehalte . Es ist ein Muss zu lesen!

acdcjunior
quelle
2
Stimmen Sie auf jeden Fall zu, dass Sie diese Aktualisierungsanforderung in Frage stellen sollten, aber manchmal muss die Benutzeroberfläche nur neu gerendert werden, da sich das Ansichtsfenster geändert hat und Sie verschiedene Assets anzeigen müssen (als ein Beispiel). Die Daten haben sich möglicherweise nicht geändert.
the_dude_abides
1
Warum müssen Sie neu laden? In einigen Fällen müssen vom Browser zwischengespeicherte Ressourcendateien (Stylesheets / js) nach einer bestimmten Zeit neu geladen werden. Ich hatte ein Stylesheet, das nach 7 Tagen neu geladen werden musste. Wenn ein Benutzer einen Tab mit Seitenzugriff offen hielt und nach 7 Tagen zurückkam, um auf dieser Seite zu navigieren, war das CSS mehr als 7 Tage alt.
Aurovrata
@AchielVolckaert Sie haben wahrscheinlich bereits die Antwort gefunden, aber ja, Vue.set()funktioniert auch innerhalb von Komponenten.
acdcjunior
1
@the_dude_abides und @ Aurovrata, das sind legitime Verwendungszwecke von Erfrischungen, da stimme ich zu. Die Frage, die ich gestellt habe, ist, dass die Leute nicht selten aus den falschen Gründen erfrischen.
Acdcjunior
1
Vielleicht versuchen Sie nur, einen Fehler in einer schlecht gestalteten Webanwendung zu beheben, die vue ausschließlich als Rendering-Tool verwendet, und beispielsweise die gesamte Anwendung neu zu laden, wenn sie auf den Server übertragen wird, wobei die clientseitigen Anwendungsfunktionen von vue ignoriert werden. In der realen Welt haben Sie nicht immer die Zeit, jeden Gräuel zu reparieren, den Sie finden.
Warren Dew
30

Bitte lesen Sie dies http://michaelnthiessen.com/force-re-render/

Der schreckliche Weg: die gesamte Seite neu laden
Der schreckliche Weg: den v-if-Hack verwenden
Der bessere Weg: die integrierte forceUpdate-Methode von Vue verwenden
Der beste Weg: Schlüsselwechsel für Ihre Komponente

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

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

Ich benutze auch Uhr: in einigen Situationen.

Yash
quelle
Absolut, ich stimme dir zu!
Diamond
Ich hätte Vue fast aufgegeben. Aber dank dieser Tatsache wurde mein Vertrauen in Vue wiederhergestellt.
Jokab
Der Link zeigt nicht wirklich, wie man es auf schreckliche Weise macht, was ich leider brauche, da meine App darauf ausgelegt ist, auf schreckliche Weise zu navigieren. Eine einfache URL zur aktuellen Seite scheint nicht zu funktionieren, zumindest nicht in der App, mit der ich es zu tun habe. Daher benötige ich Anweisungen, wie man es auf schreckliche Weise macht.
Warren Dew
@WarrenDew Bitte folgen Sie: stackoverflow.com/questions/3715047/…
Yash
25

Versuchen Sie, this.$router.go(0);die aktuelle Seite manuell neu zu laden.

Poy Chang
quelle
3
Einfacher: this. $ Router.go ()
Marius
Eigentlich @MariusAndreiana - die .go () -Funktion erfordert 1 nicht optionalen Parameter
a_lovelace
23

Verwenden Sie vm.$set('varName', value). Suchen Sie nach Details in Change_Detection_Caveats .

denis.peplin
quelle
12
<my-component :key="uniqueKey" />

Verwenden this.$set(obj,'obj_key',value) und aktualisieren Sie uniqueKeyfür jedes Update den Objektwert (obj) für jedes Updatethis.uniqueKey++

es hat bei mir so funktioniert

Pushkar Shirodkar
quelle
6

Sie können dies also auf zwei Arten tun:

1). Sie können $forceUpdate()in Ihrem Methodenhandler verwenden, dh

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

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

2). Sie können :keyIhrer Komponente ein Attribut und eine Erhöhung zuweisen, wenn Sie erneut rendern möchten

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

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

mit der v-if-Direktive

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

Wenn Sie also einfach den Wert von truevalue von false auf true ändern, wird die Komponente zwischen div erneut erneut gerendert

Geoff
quelle
1
Meiner Meinung nach ist dies der sauberste Weg, um eine Komponente neu zu laden. Obwohl in der Methode created () Sie können einige Initialisierungselemente hinzufügen.
Piotr Żak
5

Stoppen Sie die langen Codierungen, um die Komponente neu zu laden / neu zu rendern / zu aktualisieren. Dafür gibt es eine Vue.JS-Methode.

Verwenden Sie einfach das :keyAttribut.

Beispielsweise:

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

Ich benutze diesen im BS Vue Table Slot. Ich sage, dass ich etwas für diese Komponente tun werde, also mache sie einzigartig.

Felix Labayen
quelle
3

Das hat bei mir funktioniert.

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

Die andere Komponente löst das Update-Stores-List-Ereignis aus, wodurch die aktuelle Komponente erneut gerendert wird

sean717
quelle
2

Ich habe einen Weg gefunden. Es ist ein bisschen hacky, funktioniert aber.

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

Wo vmist Ihr Ansichtsmodellobjekt undx ist eine nicht vorhandene Variable?

Vue.js beschwert sich darüber im Konsolenprotokoll, löst jedoch eine Aktualisierung aller Daten aus. Getestet mit Version 1.0.26.

Laszlo der Zauberer
quelle
2

Hat für mich gearbeitet

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

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

Fügen Sie einfach diesen Code hinzu:

this.$forceUpdate()

Viel Glück

RahmanRezaee
quelle
0

: key = "$ route.params.param1" Verwenden Sie einfach den Schlüssel mit Ihren Parametern, deren Kinder automatisch neu laden.

Rai Ahmad Fraz
quelle
4
Versuchen Sie, detaillierte Informationen zu Ihrer Lösung zu geben.
Fügen
0

Ich hatte dieses Problem mit einer Bildergalerie, die ich aufgrund von Änderungen, die auf einer anderen Registerkarte vorgenommen wurden, erneut rendern wollte. Also tab1 = imageGallery, tab2 = FavoriteImages

tab @ change = "updateGallery ()" -> Dies zwingt meine v-for-Direktive, die Funktion filteredImages bei jedem Tabwechsel zu verarbeiten.

<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>
Jason
quelle
0

Entschuldigung, außer der Methode zum erneuten Laden von Seiten (Flackern), keiner von ihnen funktioniert für mich (: Schlüssel hat nicht funktioniert).

und ich habe diese Methode aus dem alten vue.js Forum gefunden, die für mich funktioniert:

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>
Segelfisch009
quelle