Vue.js全球活动巴士

时间:2016-06-27 22:14:57

标签: javascript vue.js

我正在尝试创建一个全局事件总线,以便两个兄弟组件可以相互通信。我四处寻找;但是,我找不到任何实现方法的例子。这就是我到目前为止所做的:

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()中我做错了什么。

4 个答案:

答案 0 :(得分:30)

问题是在bus.$on函数中,this指的是总线。您只需要使用.bind()将当前Vue实例绑定到该函数:

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

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

编辑:由于此页面似乎获得了大量点击,我想编辑并添加另一种方法,根据评论中的每个ChristopheMarois:

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

或删除提醒:

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

答案 1 :(得分:3)

在编写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

答案 2 :(得分:3)

这是很久以前的回答,这是我在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 :(得分:0)

这个怎么样?假设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)

作为旁注,请尝试使用Event-Bus模式作为最后的手段。