Tengo un componente principal con una entrada de selección que está vinculada a través del modelo v a una variable en los datos.
Además, creo componentes secundarios dinámicamente usando Vue.extend, que paso los propsData que también incluyen el valor de la selección.
Estos componentes tienen un observador para la propiedad que está relacionada con la entrada de selección.
Cuando creo el componente, recibe los accesorios con éxito. El problema surge cuando actualizo el valor de la entrada de selección que no activa el observador en el componente secundario.
He estado buscando situaciones similares pero no he encontrado algo que me ayude a resolver este problema, no sé por qué no activa el observador en el componente secundario cuando cambia la entrada de selección.
Cualquier ayuda sería muy apreciada.
Aquí creo el componente dinámicamente:
let PresupuestoFormularioVue = Vue.extend(PresupuestoFormulario) let instance = new PresupuestoFormularioVue({ propsData: { //The prop related to select input seguro: this.seguro, } }) instance.$mount() this.$refs.formularioContenedor.appendChild(instance.$el)Y este es el observador en el componente que no funciona:
watch:{ seguro:{ handler: function( newVal ){ console.log(newVal) }, }, },No es el watch lo que no funciona. Son las ataduras. Está asignando el valor actual de this.seguro , no el objeto reactivo en sí. Sin embargo, un new Vue() puede agregar este enlace por usted.
Como nota al margen, si PresupuestoFormulario es un Vue.extend() no importa. Puede ser cualquier VueConstructor válido: un Vue.extend() , Vue.component() o un SFC válido (con nombre y plantilla): export default {...} .
Aquí está cómo hacerlo:
methods: { addPresupuestoFormulario() { const div = document.createElement('div'); this.$el.appendChild(div); new Vue({ components: { PresupuestoFormulario }, render: h => h("presupuesto-formulario", { props: { seguro: this.seguro } }) }).$mount(div) } } El <div> agregado inicialmente al padre se reemplazará al montarlo con la plantilla real de PresupuestoFormulario y los enlaces se establecerán, exactamente como si tuviera <presupuesto-formulario :seguro="seguro" /> en la plantilla padre del comienzo.
La parte realmente interesante de esto es que el componente principal no necesita tener PresupuestoFormulario declarado en sus components .
Aquí hay un ejemplo de trabajo:
const Test = Vue.component('test', { template: `<div>message: {{message}}</div>`, props: ['message'], watch: { message: console.log } }) new Vue({ el: '#app', data: () => ({ msg: "¯\\_(ツ)_/¯" }), methods: { addComponent() { const div = document.createElement("div"); this.$el.appendChild(div); new Vue({ components: { Test }, render: h => h("test", { props: { message: this.msg } }) }).$mount(div); } } }) <script src="https://cdn.jsdelivr.net/npm/vue@2"></script> <div id="app"> <input v-model="msg"> <button @click="addComponent">Add dynamic child</button> </div> Una nota separada, sobre el uso de this.$el.appendChild() . Si bien esto funciona cuando usa una instancia raíz de Vue (la llamada aplicación Vue), es probable que falle cuando usa un componente normal de Vue, ya que los componentes de Vue2 están limitados a tener solo 1 elemento raíz.
Probablemente sea una buena idea tener un contenedor vacío (p. ej.: <div ref="container" /> ) en el padre y usar this.$refs.container.appendChild() en su lugar.
Todos los accesorios que desea verificar en el observador deben ser una función. Si desea leer más sobre esto, vaya a vue document codegrepper .
watch: { // whenever seguro changes, this function will run seguro: function (newValue, oldValue) { console.log(newValue,oldValue) } }