¿Puedes forzar a Vue.js a recargar / re-renderizar?


231

Solo una pregunta rápida.

¿Puedes forzar Vue.jsa recargar / recalcular todo? ¿Si es así, cómo?


Podría obtener un mejor soporte aquí github.com/vuejs/Discussion/issues
Cory Danielson

Genial, no sabía sobre ese lugar de discusión. Intentaré por allá.
Dave

¿Terminaste recibiendo una respuesta? Tengo muchas ganas de saber también.
Oddman

No recuerdo exactamente Pero aquí está el problema que abrí con algunas pistas: github.com/vuejs/Discussion/issues/356
Dave

Tengo la directiva v-for en la vista y tengo un caso de uso cuando cambio manualmente dos objetos en esa matriz. Vue no vuelve a generar la plantilla automáticamente después de esto. Utilicé una solución alternativa: solo haga cualquier acción con esta matriz (empuje el objeto vacío y luego empalme): esto desencadena la reproducción. Pero este es un caso especial.
Fyodor Khruschov

Respuestas:


237

Prueba este hechizo mágico:

vm.$forceUpdate();

No es necesario crear ningún vars colgante :)

Actualización: encontré esta solución cuando solo comencé a trabajar con VueJS. Sin embargo, una exploración más profunda demostró este enfoque como una muleta. Por lo que recuerdo, en un tiempo lo eliminé simplemente poniendo todas las propiedades que no se actualizaron automáticamente (en su mayoría anidadas) en propiedades calculadas.

Más información aquí: https://vuejs.org/v2/guide/computed.html


44
Esto realmente me ayudó cuando lo estaba usando con un componente de asistente de formularios en Vue. Mis campos de formulario estaban perdiendo estado aunque las variables de datos estaban intactas. Ahora estoy usando esto para actualizar las vistas cuando regrese, tuve que colocarlo en la función setTimeout.
Jimmy Ilenloa

26
Tenga en cuenta que en los archivos vue necesita 'this. $ ForceUpdate ();'
Katinka Hesselink

1
Esto funciona muy bien para actualizar un después de una larga llamada axios.
AlfredBr

44
De alguna manera absolutamente extraña, $forceUpdate()NUNCA funcionó para mí en 2.5.17.
Abana Clara

2
@AbanaClara $ forceUpdate () nunca fue un método público, lo encontré cavando el código fuente de Vue. Y dado que su uso nunca fue la forma correcta de Vue'ing, tal vez podría eliminarse. No puedo decir con certeza si todavía está allí, ya que ya no hago front-end.
Boris Mossounov

82

Esto parece una solución bastante limpia de matthiasg en este tema :

También puede usar :key="someVariableUnderYourControl"y cambiar la clave cuando desee que el componente se reconstruya por completo

Para mi caso de uso, estaba alimentando un getter Vuex en un componente como accesorio. De alguna manera, Vuex obtendría los datos, pero la reactividad no se activaría de manera confiable para volver a generar el componente. En mi caso, establecer el componente keyen algún atributo en el accesorio garantiza una actualización cuando los captadores (y el atributo) finalmente se resuelven.


1
Este es un pequeño truco, básicamente obliga a una nueva instancia del componente ( mountedse ejecutará, etc.)
btk

1
@btk Estoy de acuerdo, probablemente no sea la forma "correcta" de hacer las cosas, pero es un truco bastante limpio, por lo que es.
Brian Kung

1
Esto es útil. Utilizo la ruta completa como clave para volver a generar el mismo componente cuando la ruta cambia. : key = "$ route.fullPath"
Nirav Gandhi el

44

¿Por qué?

... ¿ necesitas forzar una actualización?

Quizás no esté explorando Vue en su mejor momento:

Para que Vue reaccione automáticamente a los cambios de valor, los objetos deben declararse inicialmente endata . O, si no, deben agregarse usandoVue.set() .

Vea los comentarios en la demostración a continuación. O abra la misma demostración en un JSFiddle aquí .

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>

Para dominar esta parte de Vue, consulte los documentos oficiales sobre reactividad : advertencias de detección de cambios . ¡Esta es una lectura obligatoria!


2
Definitivamente está de acuerdo en que debe cuestionar este requisito de actualización, pero a veces solo necesita la interfaz de usuario para volver a renderizar porque la ventana gráfica ha cambiado y necesita mostrar diferentes activos (como un ejemplo). Es posible que los datos no hayan cambiado realmente.
the_dude_abides

1
¿Por qué necesitas recargar? En algunos casos, los archivos de recursos (hojas de estilo / js) almacenados en caché por el navegador deben volver a cargarse después de un cierto período de tiempo. Tenía una hoja de estilo que necesitaba ser recargada después de 7 días y si un usuario mantenía una pestaña abierta con acceso a la página y volvía después de 7 días para navegar por esa página, el css tenía más de 7 días.
Aurovrata

@AchielVolckaert probablemente ya haya encontrado la respuesta, pero sí, Vue.set()también funciona dentro de los componentes.
acdcjunior

1
@the_dude_abides y @ Aurovrata, esos son usos legítimos de refresco, estoy de acuerdo. La pregunta que planteé es que las personas no rara vez hacen la actualización por las razones equivocadas.
acdcjunior

1
Tal vez solo esté tratando de corregir un error en una aplicación web mal diseñada que usa vue simplemente como una herramienta de representación y, por ejemplo, recarga toda la aplicación cada vez que va al servidor, ignorando las capacidades de aplicación de vue del lado del cliente. En el mundo real, no siempre tienes el tiempo para arreglar cada abominación que encuentres.
Warren Dew

30

Por favor lea esto http://michaelnthiessen.com/force-re-render/

La forma horrible: recargar toda la página
La forma terrible: usar el truco v-if
La mejor manera: usar el método incorporado de Vue forceUpdate
La mejor manera: cambiar las claves en su componente

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

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

También uso watch: en algunas situaciones.


¡Absolutamente, estoy de acuerdo contigo!
Diamante

Casi me di por vencido con Vue. Pero gracias a esto, mi fe en Vue ha sido restaurada.
jokab

El enlace en realidad no muestra cómo hacerlo de la manera horrible, que desafortunadamente es lo que necesito ya que mi aplicación está diseñada para navegar de la manera horrible. Una URL simple a la página actual no parece funcionar, al menos no en la aplicación con la que estoy tratando, por lo que realmente necesito instrucciones sobre cómo hacerlo de la manera horrible.
Warren Dew

@WarrenDew Por favor siga: stackoverflow.com/questions/3715047/…
Yash

25

Intente usar this.$router.go(0);para recargar manualmente la página actual.


3
Más simple: esto. $ Router.go ()
Marius

En realidad @MariusAndreiana - la función .go () requiere 1 parámetro no opcional
a_lovelace



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

junto con su uso this.$set(obj,'obj_key',value) y actualización uniqueKeypara cada actualización en el valor del objeto (obj) para cada actualizaciónthis.uniqueKey++

funcionó para mí de esta manera


6

Entonces hay dos formas de hacer esto,

1) Puede usar $forceUpdate()dentro de su manejador de métodos, es decir

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

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

2) Puede :keyasignar un atributo a su componente e incremento cuando desee volver a procesar

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

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

5

usando la directiva v-if

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

Entonces, simplemente cambiando el valor del verdadero valor de falso a verdadero hará que el componente entre el div se vuelva a procesar


1
En mi opinión, esta es la forma más limpia de recargar el componente. Aunque en el método created () puede agregar algunas cosas de inicialización.
Piotr Żak

5

Para recargar / volver a renderizar / actualizar el componente, detenga las codificaciones largas. Hay una forma Vue.JS de hacer eso.

Solo usa el :keyatributo.

Por ejemplo:

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

Estoy usando ese en BS Vue Table Slot. Decir que haré algo por este componente, así que hágalo único.


3

Esto me ha funcionado.

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

El otro componente desencadena el evento refresh-stores-list hará que el componente actual se vuelva a procesar


2

Encontre un camino. Es un poco hacky pero funciona.

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

¿Dónde vmestá su objeto de modelo de vista yx es una variable inexistente?

Vue.js se quejará de esto en el registro de la consola, pero desencadena una actualización para todos los datos. Probado con la versión 1.0.26.


2

Trabajó para mi

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

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


0

: key = "$ route.params.param1" simplemente use key con sus parámetros para sus hijos de recarga automática.


44
Intente proporcionar información detallada sobre su solución. agregue su código, resalte las palabras clave
Agilanbu

0

Tuve este problema con una galería de imágenes que quería volver a mostrar debido a los cambios realizados en una pestaña diferente. Entonces tab1 = imageGallery, tab2 = favoriteImages

tab @ change = "updateGallery ()" -> esto obliga a mi directiva v-for a procesar la función filterImages cada vez que cambio de pestañas.

<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

lo siento chicos, excepto el método de recarga de página (parpadeo), ninguno de ellos funciona para mí (: la clave no funcionó).

y encontré este método en el antiguo foro vue.js que funciona para mí:

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>
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.