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?


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


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.


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!


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.


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.


3
Einfacher: this. $ Router.go ()
Marius

Eigentlich @MariusAndreiana - die .go () -Funktion erfordert 1 nicht optionalen Parameter
a_lovelace



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


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>

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


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.


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


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.


2

Hat für mich gearbeitet

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

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


0

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


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>

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>
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.