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 processMethodsQueuepara um mixin ...