Eu tenho dois componentes aninhados, qual é a maneira correta de acessar os métodos filhos do pai?
this.$children[0].myMethod()
parece funcionar, mas é bem feio, não é, o que pode ser melhor maneira:
<script>
import child from './my-child'
export default {
components: {
child
},
mounted () {
this.$children[0].myMethod()
}
}
</script>
javascript
vue.js
al3x
fonte
fonte
Respostas:
Você pode usar 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 }, })
Se você não gosta de acoplamento forte, pode usar o Event Bus conforme mostrado por @Yosvel Quintero. Abaixo está outro exemplo de como usar o barramento de eventos passando no barramento como suporte.
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 do 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/
fonte
this.$refs.
, não deve carregar componente filho dinamicamente.this.$ref.ref
parece retornar uma matriz. Então, para mimthis.$refs.ref[0].autofocus();
funcionouComunicação pai-filho no VueJS
Dado que uma instância raiz do Vue pode ser acessada por todos os descendentes via
this.$root
, um componente pai pode acessar os componentes filhos viathis.$children
array e um componente filho pode acessar seu pai viathis.$parent
, seu primeiro instinto pode ser acessar esses componentes diretamente.A documentação do VueJS alerta contra isso especificamente por duas razões muito boas:
A solução é usar a interface de eventos personalizados do Vue
A interface de eventos implementada pelo Vue permite que você se comunique para cima e para baixo na árvore de componentes. Aproveitando a interface de evento personalizado, você tem acesso a quatro métodos:
$on()
- permite que você declare um ouvinte em sua instância Vue com o qual ouvir eventos$emit()
- permite que você acione eventos na mesma instância (self)Exemplo usando
$on()
e$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>
Resposta retirada da postagem original: Comunicação entre componentes no VueJS
fonte
O barramento de referência e de evento apresenta problemas quando a renderização do controle é afetada por
v-if
. Então, decidi ir com um método mais simples.A ideia é usar um array como uma fila para enviar métodos que precisam ser chamados para o componente filho. Assim que o componente for montado, ele processará essa fila. Ele observa a fila para executar novos métodos.
(Pegando emprestado algum código da resposta de Desmond Lua)
Código do componente pai:
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 é o 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>
E há muito espaço para melhorias, como mudar
processMethodsQueue
para um mixin ...fonte
Para comunicar um componente filho com outro componente filho, criei um método no pai que chama um método em um filho com:
this.$refs.childMethod()
E da outra criança chamei o método raiz:
this.$root.theRootMethod()
Funcionou para mim
fonte