web-dev-qa-db-fra.com

$ émet un événement de l'enfant au parent dans la syntaxe vue.js, es6

Je suis assez nouveau sur Vue.js et j'utilise la syntaxe ES6 avec vue-class-component. J'ai un problème en essayant d'émettre un événement d'un enfant à son parent.

J'ai suivi la logique de la syntaxe Vue.js par défaut mais je n'arrive pas à faire en sorte que mon parent intercepte un événement émis par l'enfant. Code:

Composant enfant

J'ai joint un écouteur d'événements Click à chaque <li>, qui appelle une fonction qui émet un événement. L'écouteur d'événements est défini sur le parent.

 export default class HorizontalNavigation {

  handleClick (e) {
    e.preventDefault();
    // console.log(e.target.dataset.section);
    this.$emit('ChangeView', e.target.dataset.section);
  }

  render (h) {
    return (
      <div class={ style.horizontalNavigation } >
        <div class='sections-wrapper'>
          <div class={ style.sections }>
            <ol>
              <li><a on-click={ this.handleClick } href='#1' data-section='1' class='selected'>We are</a></li>
              <li><a on-click={ this.handleClick } href='#2' data-section='2'>Services</a></li>
              <li><a on-click={ this.handleClick } href='#3' data-section='3'>Cases</a></li>
              <li><a on-click={ this.handleClick } href='#4' data-section='4'>Studio</a></li>
              <li><a on-click={ this.handleClick } href='#5' data-section='5'>Career</a></li>
              <li><a on-click={ this.handleClick } href='#6' data-section='6'>Contact</a></li>
            </ol>

            <span class='filling-line' aria-hidden='true'></span>
          </div>
        </div>
      </div>
    );
  }
}

Composant parent

export default class ViewsContainer {

  ChangeView (data) {
    console.log(data);
  }

  render (h) {
      return (
        <div class={ style.restrictOverflow } >
          <HorizontalNavigation />
          <main class={ style.viewsContainer } on-ChangeView={ this.ChangeView     } >
            <SingleView dataSection='weare' id='1' class='selected' />
            <SingleView dataSection='services' id='2' />
            <SingleView dataSection='cases' id='3' />
            <SingleView dataSection='studio' id='4' />
            <SingleView dataSection='career' id='5' />
            <SingleView dataSection='contact' id='6' />
          </main>
        </div>
      );
    }
}

En suivant la syntaxe vue.js, je devrais être capable d'écouter l'événement enfant du parent, en émettant l'événement depuis l'élément, mais le parent ne semble pas attraper l'événement.

Où vais-je mal?

7
Lou

Tu dois $emit sur le modèle d'affichage que vous souhaitez recevoir votre $emit, utilisez un bus ou utilisez https://vuex.vuejs.org/en/intro.html .

Émettre directement au parent

La manière la plus simple est de simplement $emit de l'enfant directement au composant parent:

this.$parent.$emit('ChangeView', e.target.dataset.section);

C'est [~ # ~] ok [~ # ~] , mais si vous avez une longue chaîne de composants, vous devez $emit pour chaque $parent dans la chaîne.

Emission via un bus d'événements

Vous pouvez utiliser Vue pour créer un bus d'événements global très simplement. Vous créez une instance de Vue dans votre composant principal, puis tous les autres composants de votre application peuvent emit événements et utilisez on pour réagir à ces événements.

var bus = new Vue({});
var vm = new Vue({
  methods: {
    changeView() {
      bus.$emit('ChangeView', e.target.dataset.section);
    }
  });

Il est également possible d'émettre vers $root mais ce n'est pas recommandé. Cependant, si votre app devient assez complexe, vous pouvez envisager d'utiliser à la place le système de gestion d'état de Vues, ​​ vuex .

Écouter des événements

Vous pouvez écouter le $emit dans le viewmodel en utilisant $on et à l'écoute de l'événement spécifique:

    var vm = new Vue({
      created() {
         this.$on('ChangeView', section => {
            console.log(section);
          });
      }
    );

Ce serait également similaire si vous utilisiez le bus, mais vous référeriez simplement le bus à la place:

bus.$on('ChangeView, ...);

Et vous pouvez également l'utiliser directement dans votre html en utilisant v-on:

<div v-on:ChangeView="doSomething"></div>
36
craig_h

Sauf si je manque quelque chose (très probablement), dans un exemple simple comme celui-ci, il vous suffit d'écouter l'événement emitted dans votre composant. Par exemple, dans votre élément parent, vous auriez:

<HorizontalNavigation v-on:ChangeView={this.ChangeView} />

Ensuite, dans votre composant enfant (HorizontalNavigation), vous feriez emit l'événement 'ChangeView':

this.$emit('ChangeView', e.target.dataset.section);

J'ai moi-même essayé cela dans un code similaire, basé sur un commentaire que vous avez fait sur la réponse de @ craig_h, et c'était ce dont j'avais besoin. Je n'avais pas besoin de emit pour être parent, ou utiliser un bus, ou vuex.

3
cam8001

Dans Vue, vous pouvez communiquer depuis les enfants jusqu'aux composants parents en en émettant des événements . Le composant enfant 'émet' un événement avec $emit & le composant parent l'écoute comme ceci:

Composant enfant:

<template>
  <div>
    <button @click="this.handleClick">Click me!</button>
  </div>
</template>

<script>
export default {
  name: "BaseButton",
  methods: {
    handleClick: function() {
      this.$emit("clickFromChildComponent");
    }
  }
};
</script>

<style scoped>

</style>

Composant parent:

<template>
  <div class="home">
    <h1>Passing a event from child up to parent!</h1>
    <BaseButton @clickFromChildComponent="handleClickInParent"/>
  </div>
</template>

<script>
import BaseButton from "./BaseButton";

export default {
  components: {
    BaseButton
  },
  name: "Home",
  methods: {
    handleClickInParent: function() {
      alert('Event accessed from parent!');
    }
  }
};
</script>

<style scoped>

</style>

Vous pouvez trouver un exemple d'implémentation de code de travailici et l'utiliser dans votre propre contexte .

1
Manuel Abascal