javascript - versiones - ¿Puedes forzar a Vue.js a recargar/re-renderizar?
vue.js tutorial español (14)
¿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 en los
data
. 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!
Solo una pregunta rápida.
¿Puedes obligar a Vue.js a recargar / recalcular todo? ¿Si es así, cómo?
: key = "$ route.params.param1" simplemente use key con sus parámetros para sus hijos de recarga automática.
Claro ... simplemente puede usar el atributo clave para forzar el renderizado (recreación) en cualquier momento.
<mycomponent :key="somevalueunderyourcontrol"></mycomponent>
Consulte https://jsfiddle.net/mgoetzke/epqy1xgf/ para ver un ejemplo.
También se discutió aquí: https://github.com/vuejs/Discussion/issues/356#issuecomment-336060875
Encontre un camino. Es un poco hacky pero funciona.
vm.$set("x",0);
vm.$delete("x");
Donde
vm
es su objeto de modelo de vista, y
x
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.
Esto me ha funcionado.
created() {
EventBus.$on(''refresh-stores-list'', () => {
this.$forceUpdate();
});
},
El otro componente dispara el evento refresh-stores-list hará que el componente actual se vuelva a procesar
Esto parece una solución bastante limpia de matthiasg en github.com/vuejs/Discussion/issues/356 :
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 la
key
del componente en algún atributo en el accesorio garantizaba una actualización cuando los captadores (y el atributo) finalmente se resolvieron.
Intente usar
this.$router.go(0);
para recargar manualmente la página actual.
Para recargar / volver a renderizar / actualizar el componente, detenga las codificaciones largas. Hay una forma Vue.JS de hacer eso.
Solo usa
:key
atributo
:key
.
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.
Por favor lea esto http://michaelnthiessen.com/force-re-render/
La forma horrible: recargar toda la página
La forma terrible: usar el hack v-if
La mejor manera:
usando el método de actualización de fuerza incorporado de Vue
La mejor manera: cambio de
clave 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.
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 mayor exploración demostró este enfoque como una muleta. Por lo que recuerdo, en un momento me libré de él 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
Trabajó para mi
data () {
return {
userInfo: null,
offers: null
}
},
watch: {
''$route''() {
this.userInfo = null
this.offers = null
this.loadUserInfo()
this.getUserOffers()
}
}
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ña.
<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>
Use
vm.$set(''varName'', value)
.
Busque detalles en
Change_Detection_Caveats
.
usando la directiva v-if
<div v-if="trulyvalue">
<component-here />
</div>
Entonces, simplemente cambiando el valor del valor verdadero de falso a verdadero hará que el componente entre el div se vuelva a procesar