Tengo dos componentes anidados, ¿cuál es la forma correcta de acceder a los métodos secundarios del padre?
this.$children[0].myMethod()
parece hacer el truco, pero es bastante feo, ¿no? ¿Qué puede ser mejor?
<script>
import child from './my-child'
export default {
components: {
child
},
mounted () {
this.$children[0].myMethod()
}
}
</script>
javascript
vue.js
al3x
fuente
fuente
Respuestas:
Puede utilizar ref .
import ChildForm from './components/ChildForm' new Vue({ el: '#app', data: { item: {} }, template: ` <div> <ChildForm :item="item" ref="form" /> <button type="submit" @click.prevent="submit">Post</button> </div> `, methods: { submit() { this.$refs.form.submit() } }, components: { ChildForm }, })
Si no le gusta el acoplamiento estrecho, puede usar Event Bus como lo muestra @Yosvel Quintero. A continuación se muestra otro ejemplo de uso de bus de eventos pasando el bus como accesorios.
import ChildForm from './components/ChildForm' new Vue({ el: '#app', data: { item: {}, bus: new Vue(), }, template: ` <div> <ChildForm :item="item" :bus="bus" ref="form" /> <button type="submit" @click.prevent="submit">Post</button> </div> `, methods: { submit() { this.bus.$emit('submit') } }, components: { ChildForm }, })
Código de componente.
<template> ... </template> <script> export default { name: 'NowForm', props: ['item', 'bus'], methods: { submit() { ... } }, mounted() { this.bus.$on('submit', this.submit) }, } </script>
https://code.luasoftware.com/tutorials/vuejs/parent-call-child-component-method/
fuente
this.$refs.
, no debe cargar el componente secundario de forma dinámica.Comunicación entre padres e hijos en VueJS
Dado que todos los descendientes
this.$root
pueden acceder a una instancia raíz de Vue , un componente principal puede acceder a los componentes secundarios a través de lathis.$children
matriz, y un componente secundario puede acceder a su principalthis.$parent
, su primer instinto podría ser acceder a estos componentes directamente.La documentación de VueJS advierte contra esto específicamente por dos muy buenas razones:
La solución es utilizar la interfaz de eventos personalizada de Vue
La interfaz de eventos implementada por Vue le permite comunicarse hacia arriba y hacia abajo en el árbol de componentes. Aprovechar la interfaz de eventos personalizados le brinda acceso a cuatro métodos:
$on()
- le permite declarar un oyente en su instancia de Vue con el que escuchar eventos$emit()
- le permite activar eventos en la misma instancia (auto)Ejemplo usando
$on()
y$emit()
:const events = new Vue({}), parentComponent = new Vue({ el: '#parent', ready() { events.$on('eventGreet', () => { this.parentMsg = `I heard the greeting event from Child component ${++this.counter} times..`; }); }, data: { parentMsg: 'I am listening for an event..', counter: 0 } }), childComponent = new Vue({ el: '#child', methods: { greet: function () { events.$emit('eventGreet'); this.childMsg = `I am firing greeting event ${++this.counter} times..`; } }, data: { childMsg: 'I am getting ready to fire an event.', counter: 0 } });
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.28/vue.min.js"></script> <div id="parent"> <h2>Parent Component</h2> <p>{{parentMsg}}</p> </div> <div id="child"> <h2>Child Component</h2> <p>{{childMsg}}</p> <button v-on:click="greet">Greet</button> </div>
Respuesta tomada de la publicación original: Comunicación entre componentes en VueJS
fuente
Ref y event bus tienen problemas cuando su renderizado de control se ve afectado por
v-if
. Entonces, decidí ir con un método más simple.La idea es usar una matriz como cola para enviar métodos que deben llamarse al componente secundario. Una vez que se montó el componente, procesará esta cola. Observa la cola para ejecutar nuevos métodos.
(Tomando prestado un código de la respuesta de Desmond Lua)
Código del componente principal:
import ChildComponent from './components/ChildComponent' new Vue({ el: '#app', data: { item: {}, childMethodsQueue: [], }, template: ` <div> <ChildComponent :item="item" :methods-queue="childMethodsQueue" /> <button type="submit" @click.prevent="submit">Post</button> </div> `, methods: { submit() { this.childMethodsQueue.push({name: ChildComponent.methods.save.name, params: {}}) } }, components: { ChildComponent }, })
Este es el código para ChildComponent
<template> ... </template> <script> export default { name: 'ChildComponent', props: { methodsQueue: { type: Array }, }, watch: { methodsQueue: function () { this.processMethodsQueue() }, }, mounted() { this.processMethodsQueue() }, methods: { save() { console.log("Child saved...") }, processMethodsQueue() { if (!this.methodsQueue) return let len = this.methodsQueue.length for (let i = 0; i < len; i++) { let method = this.methodsQueue.shift() this[method.name](method.params) } }, }, } </script>
Y hay mucho margen de mejora, como pasar
processMethodsQueue
a un mixin ...fuente
Para comunicar un componente secundario con otro componente secundario, he creado un método en padre que llama a un método en un niño con:
this.$refs.childMethod()
Y del otro niño llamé al método raíz:
this.$root.theRootMethod()
Funcionó para mí.
fuente