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()
.
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);
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>
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
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.