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.