Czy możesz zmusić Vue.js do ponownego załadowania / ponownego renderowania?


231

Krótkie pytanie.

Czy możesz zmusić Vue.jsdo ponownego załadowania / ponownego obliczenia wszystkiego? Jeśli tak to jak?



Świetnie, nie wiedziałem o tym miejscu dyskusji. Spróbuję tam.
Dave

Czy otrzymałeś odpowiedź? Chciałbym też wiedzieć.
Oddman

Nie pamiętam dokładnie. Ale oto problem, który otworzyłem z pewnymi wskazówkami: github.com/vuejs/Discussion/issues/356
Dave

Mam w widoku dyrektywę v-for i mam przypadek użycia, gdy ręcznie zamieniam dwa obiekty w tej tablicy. Po tym Vue nie ponownie automatycznie wyśle ​​szablonu. Użyłem obejścia: po prostu wykonaj dowolną akcję z tą tablicą (wypchnij pusty obiekt, a następnie splataj) - to wyzwala ponowne wysyłanie. Ale to jest szczególny przypadek.
Fiodor Chruszczow

Odpowiedzi:


237

Wypróbuj to magiczne zaklęcie:

vm.$forceUpdate();

Nie trzeba tworzyć żadnych wiszących stojaków :)

Aktualizacja: Znalazłem to rozwiązanie, kiedy zacząłem pracować z VueJS. Jednak dalsze badania potwierdziły to podejście jako kulę. O ile pamiętam, po pewnym czasie się go pozbyłem, po prostu umieszczając wszystkie właściwości, które nie odświeżyły się automatycznie (głównie te zagnieżdżone) w właściwościach obliczeniowych.

Więcej informacji tutaj: https://vuejs.org/v2/guide/computed.html


4
to naprawdę pomogło mi, gdy korzystałem z komponentu kreatora formularzy w Vue. Moje pola pól formularza traciły stan, chociaż zmienne danych były nienaruszone. Teraz używam tego do odświeżania widoków, kiedy wracam, musiałem umieścić go w funkcji setTimeout.
Jimmy Ilenloa,

26
Zauważ, że w plikach Vue potrzebujesz 'this. $ ForceUpdate ();'
Katinka Hesselink

1
Działa to świetnie w przypadku aktualizacji po długim wywołaniu axios.
AlfredBr

4
W jakiś absolutnie dziwny sposób $forceUpdate()NIGDY nie działała dla mnie 2.5.17.
Abana Clara,

2
@AbanaClara $ forceUpdate () nigdy nie była metodą publiczną, odkryłem, że kopie kod źródłowy Vue. A ponieważ jego użycie nigdy nie było właściwym sposobem Vue'ing, być może można je rozebrać. Nie mogę powiedzieć na pewno, czy nadal tam jest, ponieważ nie robię już frontonu.
Boris Mossounov,

82

Wydaje się, że to całkiem czyste rozwiązanie Matthiasga w tej sprawie :

możesz także użyć :key="someVariableUnderYourControl"i zmienić klucz, jeśli chcesz całkowicie odbudować komponent

W moim przypadku użyłem gettera Vuex do komponentu jako rekwizytu. Jakoś Vuex pobierałby dane, ale reaktywność nie uruchamiałaby się rzetelnie w celu ponownego wysłania komponentu. W moim przypadku ustawienie komponentu keyna jakiś atrybut rekwizytu gwarantowało odświeżenie, gdy gettery (i atrybut) w końcu zostały rozwiązane.


1
Jest to fajna sztuczka, w zasadzie wymusza ponowne utworzenie instancji komponentu ( mountedzostanie uruchomione itp.)
btk

1
@btk Zgadzam się, prawdopodobnie nie jest to „właściwy” sposób na robienie rzeczy, ale jest to dość czysty hack, do tego, co to jest.
Brian Kung

1
to pomocne. Używam pełnej ścieżki trasy jako klucza do ponownego wysłania tego samego komponentu po zmianie trasy. : key = "$ route.fullPath"
Nirav Gandhi

44

Czemu?

... czy musisz wymusić aktualizację?

Być może nie eksplorujesz Vue w najlepszym wydaniu:

Aby Vue automatycznie reagował na zmiany wartości, obiekty muszą być wstępnie zadeklarowane wdata . Lub, jeśli nie, należy je dodać za pomocąVue.set() .

Zobacz komentarze w pokazie poniżej. Lub otwórz to samo demo w JSFiddle tutaj .

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>

Aby opanować tę część Vue, sprawdź oficjalne dokumenty dotyczące reaktywności - zastrzeżenia dotyczące wykrywania zmian . To trzeba przeczytać!


2
Zdecydowanie zgadzam się, że powinieneś zakwestionować to wymaganie odświeżania, ale czasami potrzebujesz tylko interfejsu użytkownika do ponownego renderowania, ponieważ zmieniła się rzutnia i musisz pokazać różne zasoby (jako jeden przykład). Dane mogły się nie zmienić.
the_dude_abides

1
Dlaczego musisz przeładować? W niektórych przypadkach pliki zasobów (arkusze stylów / js) buforowane przez przeglądarkę muszą zostać ponownie załadowane po pewnym czasie. Miałem arkusz stylów, który musiałem ponownie załadować po 7 dniach, a jeśli użytkownik pozostawił otwartą kartę z dostępem do strony i wrócił po 7 dniach, aby nawigować po tej stronie, css miał więcej niż 7 dni.
Aurovrata

@AchielVolckaert prawdopodobnie już znalazłeś odpowiedź, ale tak, Vue.set() działa również wewnątrz komponentów.
acdcjunior

1
@the_dude_abides i @ Aurovrata, są to uzasadnione zastosowania odświeżania, zgadzam się. Zadałem pytanie, że ludzie nierzadko robią odświeżenie z niewłaściwych powodów.
acdcjunior

1
Być może po prostu próbujesz naprawić błąd w źle zaprojektowanej aplikacji internetowej, która używa vue wyłącznie jako narzędzia do renderowania, i na przykład ponownie ładuje całą aplikację za każdym razem, gdy trafia ona na serwer, ignorując możliwości vue po stronie klienta. W prawdziwym świecie nie zawsze masz czas na naprawienie każdej znalezionej obrzydliwości.
Warren Dew,

30

Proszę przeczytać to http://michaelnthiessen.com/force-re-render/

Okropny sposób: przeładowanie całej strony
Okropny sposób: użycie hakowania v-if
Lepszy sposób: użycie wbudowanej metody forceUpdate Vue
Najlepszy sposób: zmiana klucza w komponencie

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

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

Używam również zegarka: w niektórych sytuacjach.


Oczywiście, zgadzam się z tobą!
Diament,

Prawie zrezygnowałem z Vue. Ale dzięki temu moja wiara w Vue została przywrócona.
jokab

Link tak naprawdę nie pokazuje, jak to zrobić w okropny sposób, czego niestety potrzebuję, ponieważ moja aplikacja jest zaprojektowana do poruszania się w okropny sposób. Prosty adres URL do bieżącej strony nie działa, przynajmniej nie w aplikacji, z którą mam do czynienia, więc tak naprawdę potrzebuję instrukcji, jak to zrobić w straszny sposób.
Warren Dew


25

Spróbuj użyć this.$router.go(0);do ręcznego ponownego załadowania bieżącej strony.


3
Prostsze: to. $ Router.go ()
Marius

Właściwie @MariusAndreiana - funkcja .go () wymaga 1 nie opcjonalnego parametru
a_lovelace



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

wraz z nim używaj this.$set(obj,'obj_key',value) i aktualizuj uniqueKeydla każdej aktualizacji wartości obiektu (obj) dla każdej aktualizacjithis.uniqueKey++

działało dla mnie w ten sposób


6

Więc możesz to zrobić na dwa sposoby,

1). Możesz użyć $forceUpdate()w swoim module obsługi metody, tj

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

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

2). Możesz nadać :keyatrybut swojemu komponentowi i zwiększyć go, gdy chcesz ponownie wysłać

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

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

5

za pomocą dyrektywy v-if

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

Tak więc po prostu poprzez zmianę wartości truevalue z false na true spowoduje ponowne przesłanie komponentu między div


1
Moim zdaniem jest to najczystszy sposób na ponowne załadowanie komponentu. Chociaż w metodzie Created () można dodać kilka elementów inicjujących.
Piotr Żak,

5

Aby ponownie załadować / ponownie renderować / odświeżyć komponent, zatrzymaj długie kodowanie. Jest na to sposób Vue.JS.

Wystarczy użyć :keyatrybutu.

Na przykład:

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

Używam tego w automacie stołowym BS Vue. Mówiąc, że zrobię coś dla tego komponentu, więc uczyń go wyjątkowym.


3

To zadziałało dla mnie.

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

Drugi komponent uruchamia zdarzenie refresh-przechowuje listę, spowoduje ponowne wysłanie bieżącego komponentu


2

Znalazłem drogę. Jest trochę zuchwały, ale działa.

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

Gdzie vmjest twój obiekt modelu widoku, ix nie istnieje zmienna.

Vue.js będzie narzekać na to w dzienniku konsoli, ale powoduje odświeżenie wszystkich danych. Testowane z wersją 1.0.26.


2

Pracował dla mnie

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

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


0

: key = "$ route.params.param1" po prostu użyj klucza z dowolnymi parametrami, jego automatyczne ładowanie dzieci.


4
spróbuj podać szczegółowe informacje o swoim rozwiązaniu. dodaj swój kod, zaznacz słowa kluczowe
Agilanbu

0

Miałem ten problem z galerią obrazów, którą chciałem ponownie wysłać ze względu na zmiany wprowadzone na innej karcie. Tak więc tab1 = imageGallery, tab2 = favouriteImages

tab @ change = "updateGallery ()" -> to zmusza moją dyrektywę v-for do przetwarzania funkcji filterImages za każdym razem, gdy przełączam tabulatory.

<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

przepraszam chłopaki, z wyjątkiem metody przeładowania strony (migotanie), żaden z nich nie działa dla mnie (: klucz nie działał).

i znalazłem tę metodę ze starego forum vue.js, które działa dla mnie:

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>
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.