web-dev-qa-db-fra.com

Vue.js Global Event Bus

J'essaie de créer un bus d'événements global afin que deux composants frères puissent communiquer l'un avec l'autre. J'ai cherché autour; Cependant, je ne trouve aucun exemple de mise en œuvre. C'est ce que j'ai jusqu'ici:

var bus = new Vue();

Vue.component('Increment', {
  template: "#inc",
  data: function() {
   return ({count: 0})
  },
  methods: {
    increment: function(){
      var increment = this.count++
      bus.$emit('inc', increment)
  }
 }
})

Vue.component('Display', {
  template: "#display",
  data: function(){
  return({count: 0})
  },
 created: function(){
   bus.$on('inc', function(num){
   alert(num)
   this.count = num;
  });
 }
})


vm = new Vue({
 el: "#example",
})

J'ai créé mes modèles comme suit: http://codepen.io/p-adams/pen/PzpZBg

J'aimerais que le composant Increment communique le nombre au composant Display. Je ne suis pas sûr de ce que je fais de mal en bus.$on()

14
Mahmud Adam

Le problème est que, dans votre fonction bus.$on, this fait référence au bus. Il vous suffit de lier l'instance Vue actuelle à cette fonction à l'aide de .bind():

bus.$on('inc', function(num){
 alert(num)
 this.count = num;
}.bind(this));

Vous devez également consulter https://github.com/vuejs/vuex si vous souhaitez gérer les états d'application globaux.

EDIT: Comme cette page semble avoir reçu beaucoup de clics, je souhaite éditer et ajouter une autre méthode, selon ChristopheMarois dans les commentaires:

bus.$on('inc', (num) => {
 alert(num);
 this.count = num;
});

Ou supprimer l'alerte:

bus.$on('inc', (num) => this.count = num);
29
Jeff

Ceci est une réponse longue en arrière, voici ma solution en utilisant in vue.js-2

main.js

import Vue from 'vue'
import App from './App'

export const eventBus = new Vue({
  methods:{
    counter(num) {
      this.$emit('addNum', num);
    }
  }
});

new Vue({
  el: '#app',
  template: '<App/>',
  components: { App }
});

comp1.vue

//Calling my named export
import { eventBus } from '../../main'
<template>
  <div>
    <h1>{{ count }}</h1>
    <button @click="counterFn">Counter</button>
  </div>
</template>

<script>
  import { eventBus } from '../../main'

  export default {
    name: 'comp-one',
    data() {
      return {
        count: 0
      }
    },
    methods: {
      counterFn() {
        eventBus.counter(this.count);
      }
    },
    created() {
      eventBus.$on('addNum', () => {
        this.count++;
      })
    }
  }
</script>
3
Syed

Lorsque vous écrivez du code JavaScript ES5, vous devez être conscient du fait que ce que vous appelez en utilisant le mot clé this peut changer, en fonction de l'étendue de l'appel.

Une métaphore utile pour comprendre le concept this consiste à considérer les accolades de ES5 comme des clôtures, qui contiennent/lient leur propre this

Lorsque vous utilisez this dans la fonction de rappel de votre bus d’événements, this ne fait pas référence à votre composant Vue, mais à l’objet bus, qui ne contient pas de données count; les données que vous comptez mettre à jour ne le seront donc pas. t.

Si vous avez/souhaitez écrire la syntaxe ES5, une solution de contournement courante (en plus de la liaison this suggérée par la réponse acceptée) consiste à affecter le mot clé this à une variable comme celle-ci:

created: function(){
  var self = this;
  bus.$on('inc', function(num){
    alert(num)
    self.count = num;
  });
}

Si vous pouvez écrire ES6, faites-le autant que possible. Vous pouvez toujours compiler/transposer en ES5 avec Babel . La réponse acceptée vous montre comment utiliser les fonctions de flèche. 

Les fonctions fléchées fonctionnent dans ce cas car elles ne lient pas leur propre variable this

Pour rester avec la métaphore de la barrière: imaginez la flèche ES6 percer un trou dans votre barrière de fonction, de sorte que la variable this extérieure puisse passer et que vous puissiez appeler this comme prévu. 

Pour en savoir plus sur les fonctions de flèche ES6, visitez: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions

3
tomyam

Que dis-tu de ça? Supposons Vue.js 2.

Créez un composant Event-Bus réutilisable et associez-le à Vue via le modèle de plug-in:

// ./components/EventBus.vue
import Vue from 'vue'
export const EventBus = new Vue()

// ./plugins/EventBus.js
export default {
  install(Vue) {
    const { EventBus } = require('../components/EventBus')
    Vue.prototype.$bus = EventBus
  }
}

// ./main.js
import EventBus from './plugins/EventBus'
Vue.use(EventBus)

Ensuite, vous pouvez faire n’importe où dans votre code: this.$bus.$emit('some-event', payload)

En remarque, essayez d'utiliser le modèle Event-Bus en dernier recours.

0
adi518