Vue.js global event bus

匿名 (未验证) 提交于 2019-12-03 02:56:01

问题:

I am trying to create a global event bus so that two sibling components can communicate with each other. I have searched around; however, I cannot find any examples of how to implement one. This is what I have so far:

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", }) 

I created my templates like so: http://codepen.io/p-adams/pen/PzpZBg

I'd like the Increment component to communicate the count to the Display component. I am not sure what I am doing wrong in bus.$on().

回答1:

The problem is that within your bus.$on function, this refers to the bus. You just need to bind the current Vue instance to that function using .bind():

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

You should also check out https://github.com/vuejs/vuex if you want to manage global application states.

EDIT: Since this page seems to get a lot of clicks I want to edit and add another method, per ChristopheMarois in the comments:

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

Or removing the alert:

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


回答2:

As you write ES5 JavaScript you have to be aware of the fact that what you refer to by using the this keyword might change, according to the scope, it is called from.

A useful metaphor to get your head around the this concept is to think of the curly braces in ES5 as fences, that contain/bind its own this.

When you use this in the callback function of your event bus, this does not refer to your Vue component, but the bus object, which has no count data, so the data you expect to update doesn't.

If you have/want to write ES5 syntax a common workaround (besides binding this as suggested by the accepted answer) is to assign the this keyword to a variable like so:

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

If you can write ES6, do so whenever possible. You can always compile/transpile down to ES5 with Babel. The accepted answer shows you how by using arrow functions.

Arrow functions work in that case because they do not bind their own this.

To stick with the fence metaphor: imagine the ES6 arrow poking a hole in your function fence, so the outer this can pass through and you can call this as intended.

To learn more about ES6 arrow functions visit: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions



回答3:

This is answered long back, here is my solution using 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> 


回答4:

How about this? Assume Vue.js 2.

Create a reusable Event-Bus component and attach it to Vue via plugin pattern:

// ./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) 

Then, you can do anywhere in your code: this.$bus.$emit('some-event', payload)

As a side note, try to utilize the Event-Bus pattern as last resort.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!