typescript - Forzar a vue.js a actualizar una prop cuando se cambia su subpropiedad
Tengo un componente que se enlaza a un objeto, y el componente padre cambia una propiedad de su objeto. El subcomponente debería reaccionar al cambio.
Subcomponente :
import { Component, Emit, Inject, Model, Prop, Provide, Vue, Watch } from 'vue-property-decorator'
@Component({
props: {
value: Object,
}
})
class ValidatedSummaryComponent extends Vue {
value: any;
field = "Name";
v: any;
created() {
console.log("!", this.value);
this.v = this.value;
}
state: string | null = null;
error = "";
@Watch('value')
onValueChanged(val: any, oldVal: any) {
console.log("Value called", val);
this.v = val;
this.onChanged();
this.$forceUpdate();
}
private onChanged() {
if (typeof this.v.validationErrors[this.field] == 'undefined') {
this.state = null;
this.error = "";
} else {
this.state = 'invalid';
this.error = this.v.validationErrors[this.field].join();
}
}
}
export default ValidatedSummaryComponent;
Uso :
<ValidatedSummary v-bind:value="bindableObject"></ValidatedSummary>
Entonces lo hago:
bindableObject.Name = 'New name'
y necesito que mi componente ValidatedSummaryComponent reaccione.
Probablemente podría vincularlo como una propiedad separada:
<ValidatedSummary v-bind:value="bindableObject.Name"></ValidatedSummary>, pero en el diseño final, el componente debería observar todas las propiedades de BindableObject y habrá varios BindableObjects diferentes con distintos conjuntos de propiedades, así que no puedo simplemente enlazarlo propiedad por propiedad.
La única manera en que logré hacer que funcionara es forzar a vue.js a actualizar todo el objeto, asegurando que la verificación de igualdad de vue.js no pase:
this.bindableObject = Object.assign(new BindableObject(), this.bindableObject );
Pero esto es muy engorroso ya que tendré que hacer esto en cada cambio, así que estoy buscando una mejor manera de manejar esto. También sería bueno eliminar this.$forceUpdate(); en el código anterior, pero puedo sobrevivir con ello.
Respuesta #1
Bueno, simplemente haz una actualización forzada. Hará tu vida más fácil
vm.$forceUpdate();
Como se menciona en los documentos
Forzar a la instancia de Vue a volver a renderizar. Tenga en cuenta que no afecta a todos los componentes hijos, solo a la propia instancia y a los componentes hijos con contenido insertado en el slot.
Sin embargo, solo se recomienda cuando no te quedan otras opciones (solo como último recurso).
Entonces, ¿qué otras opciones puedes usar para que funcione? (depende del diseño del código)
- Intenta usar Vue.set(). o,
- Reasigna el objeto modificado.
Respuesta #2
Convirtiendo mi comentario en una respuesta.
Puedes intentar usar la opción deep de watch como se muestra en el manual
