J'ai deux composants imbriqués, quelle est la bonne façon d'accéder aux méthodes enfants à partir du parent?
this.$children[0].myMethod()
semble faire l'affaire mais c'est assez moche, n'est-ce pas, quoi de mieux:
<script>
import child from './my-child'
export default {
components: {
child
},
mounted () {
this.$children[0].myMethod()
}
}
</script>
javascript
vue.js
al3x
la source
la source
Réponses:
Vous pouvez utiliser la réf .
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 vous n'aimez pas le couplage serré, vous pouvez utiliser Event Bus comme indiqué par @Yosvel Quintero. Voici un autre exemple d'utilisation du bus d'événements en passant dans le bus comme accessoires.
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 }, })
Code du composant.
<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/
la source
this.$refs.
, vous ne devriez pas charger le composant enfant de manière dynamique.Communication parent-enfant dans VueJS
Étant donné qu'une instance racine de Vue est accessible par tous les descendants via
this.$root
, un composant parent peut accéder aux composants enfants via lethis.$children
tableau, et un composant enfant peut accéder à son parent viathis.$parent
, votre premier instinct peut être d'accéder directement à ces composants.La documentation VueJS met en garde contre cela spécifiquement pour deux très bonnes raisons:
La solution est d'utiliser l'interface événementielle personnalisée de Vue
L'interface événementielle implémentée par Vue vous permet de communiquer de haut en bas dans l'arborescence des composants. L'utilisation de l'interface d'événement personnalisée vous donne accès à quatre méthodes:
$on()
- vous permet de déclarer un auditeur sur votre instance Vue avec lequel écouter les événements$emit()
- vous permet de déclencher des événements sur la même instance (self)Exemple utilisant
$on()
et$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>
Réponse tirée du message original: Communiquer entre les composants dans VueJS
la source
Ref et bus d'événements ont tous deux des problèmes lorsque le rendu de votre contrôle est affecté par
v-if
. J'ai donc décidé d'opter pour une méthode plus simple.L'idée est d'utiliser un tableau comme file d'attente pour envoyer des méthodes qui doivent être appelées au composant enfant. Une fois le composant monté, il traitera cette file d'attente. Il surveille la file d'attente pour exécuter de nouvelles méthodes.
(Empruntant du code à la réponse de Desmond Lua)
Code du composant parent:
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 }, })
Ceci est le code pour 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>
Et il y a beaucoup à faire pour s'améliorer comme passer
processMethodsQueue
à un mixin ...la source
Pour communiquer un composant enfant avec un autre composant enfant, j'ai créé une méthode dans le parent qui appelle une méthode dans un enfant avec:
this.$refs.childMethod()
Et d'un autre enfant que j'ai appelé la méthode racine:
this.$root.theRootMethod()
Cela a fonctionné pour moi.
la source