Vue.js全局事件总线

Vue.js global event bus

本文关键字:总线 事件 全局 js Vue      更新时间:2023-09-26

我正在尝试创建一个全局事件总线,以便两个兄弟组件可以相互通信。我已经四处搜索;然而,我找不到任何例子如何实现一个。这是我目前所看到的:

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

我创建了我的模板如下:http://codepen.io/p-adams/pen/PzpZBg

我希望Increment组件将计数传达给Display组件。我不确定我在bus.$on()做错了什么。

问题是在您的bus.$on函数中,this指的是总线。您只需要使用.bind():

将当前Vue实例绑定到该函数
bus.$on('inc', function(num){
 alert(num)
 this.count = num;
}.bind(this));

如果你想管理全局应用程序状态,你还应该查看https://github.com/vuejs/vuex。

编辑:由于这个页面似乎得到了很多点击,我想编辑和添加另一个方法,per ChristopheMarois在评论中:

编辑:为了使这个答案更清楚一些,这样以后的读者就不需要阅读评论了,下面是发生的事情:

使用像下面这样的粗箭头将'this'的词法范围绑定到组件而不是事件总线。

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

或者删除警告:

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

当你编写ES5 JavaScript时,你必须意识到这样一个事实,即你使用this关键字所引用的内容可能会改变,根据作用域,它是从。

让你理解this概念的一个有用的比喻是,把ES5中的花括号看作栅栏,它包含/绑定了自己的this

当您在事件总线的回调函数中使用this时,this不会引用您的Vue组件,而是引用总线对象,该对象没有计数数据,因此您期望更新的数据不会。

如果你有/想要编写ES5语法,一个常见的解决方案(除了绑定this,被接受的答案建议)是将this关键字分配给一个变量,如:

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

如果你可以写ES6,尽可能写。你总是可以用Babel编译/编译到ES5。公认的答案向您展示了如何使用箭头函数。

箭头函数在这种情况下工作,因为它们不绑定自己的this

坚持栅栏的比喻:想象一下ES6箭头在你的函数栅栏上戳了一个洞,这样外部的this就可以穿过,你就可以按预期调用this了。

要了解更多关于ES6箭头函数的信息,请访问:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions

这是回答很久以前,这是我的解决方案使用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>

这个怎么样?假设Vue.js 2.

创建一个可重用的Event-Bus组件,并通过插件模式将其附加到Vue:

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

然后,你可以在代码的任何地方做:this.$bus.$emit('some-event', payload)

作为一个边注,尝试使用事件总线模式作为最后的手段。