asynchronous - multiple - vue single file components
Los accesorios para componentes infantiles de VueJs no se actualizan al instante (1)
Por lo que yo sé, no debería necesitar eventos para pasar datos de padres a hijos.
Todo lo que necesita es, en el componente secundario: props: [''theProp'']
Y cuando se usa el componente secundario en el elemento primario: <child :theProp="someData"></child>
Ahora, en cualquier parte del elemento principal que cambie someData
, el componente secundario reaccionará en consecuencia.
No necesita eventos, no necesita "mirar", no necesita "listo".
Por ejemplo: después de una llamada AJAX, en el "listo" del padre, usted carga algunos datos:
// at the parent component
data: function () {
return {
someData: {}
}
},
ready: function () {
var vm = this;
$.get(url, function(response) {
vm.someData = response;
});
}
Ahora, no necesita nada más para pasar los datos al niño . ¡Ya está en el niño como theProp
!
Lo que realmente necesita hacer es tener, en el niño, algo que reaccione a los cambios de datos en su propiedad theProp
.
Ya sea en la interfaz:
<div v-if="theProp.id > 0">
Loaded!
</div>
O en el código JavaScript:
// at the child component
computed: {
// using a computed property based on theProp''s value
awesomeDate: function() {
if (!this.theProp || (this.theProp.length === 0)) {
return false;
}
if (!this.initialized) {
this.initCalendar();
}
return this.theProp.someThing;
}
}
Actualización 1
También puede, en el padre, representar al niño de forma condicional:
<child v-if="dataLoaded" :theProp="someData"></child>
Solo configure dataLoaded
en true cuando los datos estén disponibles.
Actualización 2
O tal vez su problema está relacionado con una advertencia de detección de cambio
Tal vez estás creando una nueva propiedad en un objeto ...
vm.someObject.someProperty = someValue
... cuando deberías ...
vm.$set(''someObject.someProperty'', someValue)
... entre otras "advertencias".
Actualización 3
En VueJS 2 no está restringido a plantillas. Puede usar una función de renderizado y codificar la lógica de renderizado más compleja que desee.
Actualización 4 (con respecto a la edición 2 de OP)
Tal vez puede dejar ready
y usar immediate
opción immediate
, por lo que su inicialización se realiza en un solo lugar:
watch: {
someData: {
handler: function (someData) {
// check someData and eventually call
this.initCalendar();
},
immediate: true
}
}
Tengo una configuración de componente principal / secundario donde el padre está cargando datos del servidor y pasándoselos a los niños a través de accesorios. En el niño me gustaría crear una instancia de un calendario jQuery con algunos de los datos que recibe del padre.
Para esperar los datos antes de configurar el calendario, transmití un evento en el padre para el que tengo una configuración de escucha de eventos en el niño.
El oyente está siendo despedido en el niño, pero si this.$log(''theProp'')
, no está definido. Sin embargo, si inspecciono los componentes con los devtools VueJs, la relación padre / hijo está allí y el niño ha recibido el accesorio mientras tanto.
El apoyo se define en el niño como un apoyo dinámico :the-prop="theProp"
. Dado que el niño recibe el accesorio al final, supongo que mi configuración es correcta, pero parece haber algún tipo de retraso. El padre establece los accesorios en la función de retorno de la llamada ajax y de nuevo: está funcionando, parece que con un ligero retraso.
También traté de registrar un oyente de watch
en el accesorio del niño para poder configurar el calendario y asegurarme de que el accesorio esté allí. Sin embargo, el detector de escucha dispara, pero this.$log(''theProp'')
aún no está definido.
Si paso los datos junto con la llamada de transmisión, como this.$broadcast(''dataLoaded'', theData)
el niño lo recibe muy bien. Pero parece incorrecto hacerlo de esa manera, ya que básicamente estoy construyendo mi propio manejador de props.
No estoy publicando ningún código porque los componentes son bastante grandes y los devtools de VueJs me dicen que la situación padre / hijo está funcionando.
¿Me falta algo de información? ¿Hay un pequeño retraso entre la configuración de un valor en el padre y el niño que lo recibe? ¿Cuál sería la forma correcta de esperar los datos de los padres en el niño?
Normalmente, cuando solo procesa los datos en la plantilla, el tiempo no importa tanto, ya que los datos están vinculados a la plantilla. Pero en este caso, realmente necesito que los datos estén allí para configurar el calendario o será incorrecto.
Gracias.
edición 1: aquí está un jsfiddle: https://jsfiddle.net/dr3djo0u/1/ Parece confirmar que los datos no están disponibles inmediatamente después de la transmisión. Sin embargo, el observador funciona, aunque casi podría jurar que a veces this.$log(''someData'')
devolvió undefined
cuando configuré ese testcase.
Pero supongo que mi problema podría estar en otro lado, voy a echar un vistazo esta noche, no tengo el proyecto conmigo en este momento.
edición 2: hice algunas pruebas más. Mi problema era que a) los oyentes del evento no parecen recibir los datos al instante yb) también estaba tratando de iniciar el calendario en la route.data
llamada someData
si someData
ya estaba presente (por ejemplo, cuando venía del padre), pero esa ruta se devolvió se llama antes de que el componente esté listo, por lo que tampoco funcionaba allí.
Mi solución es ahora esto:
// works when the child route is loaded directly and parent finishes loading someData
watch: {
someData() {
this.initCalendar();
}
},
// works when navigating from parent (data already loaded)
ready() {
if (this.someData && this.someData.length) {
this.initCalendar()
}
}