使用全局事件总线,从子组件向(祖)父组件发出Vue.js事件

4
我希望使用全局事件总线,将子组件中的事件发送到(祖先)父组件。
在我的 main.js 文件中,我将全局事件总线提供给所有组件使用。
import Vue from 'vue'
import App from './App'
const eventHub = new Vue()

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

Vue.mixin({
  data: function () {
    return {
      eventHub: eventHub
    }
  }
})

然后,在我的 Childcomponent.vue: 中,我在点击事件上向事件总线发送一个事件

<template>
  <button @click="save">Save</button>
</template>

<script>
  let data = {
    columnName: '',
    order: 0
  }

  export default {
    ...
    name: 'init-column',
    methods: {
      save: function () {
        this.eventHub.$emit('newColumn', data)
      }
    }
    ...
  }
</script>

然后,在一个名为Parentcomponent.vue的组件中,我想要捕获这个事件并对子组件传递的数据进行处理:

<template>
  <div id="app">
      <column v-for="column in allData"></column>
      <init-column v-if="newColumn"></init-column>
    </div>
  </div>
</template>

<script>
  import initColumn from './components/Init-column'

  let newColumn = false

  export default {
    ...
    name: 'project',
    ready: function () {
      this.eventHub.$on('newColumn', (event) => {
        console.log(event)
      })
    }
    ...
  }
</script>

我不确定在哪里放置$on监听器,我看到一些示例将$on放在ready hook中。然而,上面的代码什么也没做,但是控制台没有错误。


将事件中心放在自己的文件中并导出,然后在其他文件中导入以使用相同的实例。或者您可以只使用 this.$root 来进行所有事件的发射和监听。 - vbranden
3个回答

17

Vue 3中,这种能力已经消失了。下面的RFC提到了动机并提供了一些进一步帮助的链接。

https://github.com/vuejs/rfcs/blob/master/active-rfcs/0020-events-api-change.md


我认为data不是事件总线的正确位置。我也不会使用全局mixin。

我过去做过的是创建一个简单的bus.js文件,例如:

import Vue from 'vue'
export default new Vue()

然后,在需要总线的任何组件中,我只需

import bus from './bus.js'

然后我通常这样做来触发事件。

bus.$emit('foo', whatever)

以此来抓住它们

created () {
  bus.$on('foo', this.someMethod)
}

我更喜欢在created钩子函数中完成此操作,因为那是在生命周期中可以进行此操作的最早步骤。

此外,在GitHub上的这个问题中有一些非常好的例子:https://github.com/vuejs/vuejs.org/pull/435


我从官方迁移指南中了解到了mixin方法。我是一个Vue.js的初学者。除了触发事件,你还有什么其他方式可以将数据从子组件传递到父组件呢?我会查看你的Github链接。 - marchello
通常建议使用Vuex,但对于较小的项目可能过于繁琐。 - Bill Criswell
2
是的,那就是我想要避免的。这是一个相对简单的项目,我正在努力保持它的简单性。 - marchello
1
支持此类事件的功能已被移除 https://github.com/vuejs/rfcs/blob/master/active-rfcs/0020-events-api-change.md - eden m
谢谢 Eden。我会在回答的顶部提到这一点。 - Bill Criswell

0

当在创建的钩子中使用时,我会得到以下错误:Uncaught TypeError: Cannot read property '$on' of undefined - marchello
如果是这样,那么在该组件中this.eventHub将未定义。最好的方法是遵循@BillCriswell在他的答案中的示例,在bus.js中定义bus并将其导入到任何需要它的组件中。 - Mani
但是这应该是可用的,对吗?根据这个指南,如果我在$emit事件中使用console.log(this),我可以看到vue实例中的“eventHub”。然而,在$on中我就不能看到。我会尽快尝试@BillCriswell的答案。 - marchello
在该指南中,eventHub 被定义为全局变量,而不是组件的一部分。同样,在您的情况下,eventHub 仅在 main.js 中可用,而不在组件文件中。您还应该能够使用 vue-devtools 找到它是否在组件中可用。 - Mani
不再支持此类事件。 - eden m

0
我使用自定义事件获得了期望的效果:@newColumn="event"
<init-column @newColumn="event" v-if="newColumn"></init-column>
...
methods: { event: function(e) { console.log(e) }

所以每当我从子组件中使用$emit时,它确实调用了事件方法。

这很有效,但由于某种奇怪的原因,监听器$on却没有起作用。也许我在使用$on方法时漏掉了什么。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接