web-dev-qa-db-fra.com

Comment accéder à une méthode enfant à partir du parent dans vue.js

J'ai deux composants imbriqués, quel est le moyen approprié d'accéder aux méthodes enfant à partir du parent?

this.$children[0].myMethod() semble faire l'affaire mais il est plutôt moche, n'est-ce pas, quelle meilleure façon de faire:

<script>
import child from './my-child'

export default {
  components: {
   child
  },
  mounted () {
    this.$children[0].myMethod()
  }
}
</script>
48
al3x

Communication parent-enfant dans VueJS

Étant donné qu'une instance racine Vue est accessible par tous les descendants via this.$root, un composant parent peut accéder aux composants enfants via le tableau this.$children et un composant enfant peut accéder à son parent via this.$parent, votre premier réflexe pourrait être d'accéder directement à ces composants.

La documentation de VueJS met en garde contre cela spécifiquement pour deux très bonnes raisons:

  • Il couple étroitement le parent à l'enfant (et vice versa)
  • Vous ne pouvez pas compter sur l'état du parent, étant donné qu'il peut être modifié par un composant enfant.

La solution consiste à utiliser l'interface d'événements personnalisée de Vue.

L'interface événementielle implémentée par Vue vous permet de communiquer de haut en bas de l'arborescence des composants. En exploitant l’interface d’événement personnalisée, vous avez accès à quatre méthodes:

  1. $on() - vous permet de déclarer un auditeur sur votre instance Vue avec laquelle écouter des événements
  2. $emit() - vous permet de déclencher des événements sur la même instance (auto)

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 d'origine: Communication entre composants dans VueJS

24
Yosvel Quintero

Vous pouvez utiliser 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 vous n'aimez pas le couplage étroit, vous pouvez utiliser Event Bus comme indiqué par @Yosvel Quintero. Vous trouverez ci-dessous un autre exemple d’utilisation d’un bus d’événement en lui passant comme accessoire.

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 de 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/

135
Desmond Lua