NuxtJS事件总线问题:从实例属性创建的事件无法触发或接收
问题分析与解决方案
你遇到的核心问题是 setInterval 回调函数里的 this 指向错误,导致没有正确调用事件总线的 $emit 方法。咱们一步步拆解:
为什么事件没触发?
在你的 notify 函数里,虽然用 .bind(new Vue()) 绑定了外层函数的 this,但 setInterval 的回调函数是独立执行的,它内部的 this 默认指向全局对象(浏览器环境下是 window),而不是你绑定的 Vue 实例。这就导致 this.$bus 变成了 undefined,自然无法触发事件。
修复方案
这里提供几种可行的修复方式,按简洁度排序:
方案1:直接使用全局事件总线实例(最推荐)
既然你已经通过插件把 $bus 挂载到了 Vue 原型上,那完全不需要额外创建新的 Vue 实例,直接引用原型上的单例即可:
import Vue from 'vue'; export default function (_ctx, inject) { const notify = function (msg) { console.log('emitting', msg); setInterval(() => { // 直接用Vue原型上的全局bus实例 Vue.prototype.$bus.$emit('add', msg); }, 500); }; inject('notify', notify); }
方案2:用箭头函数继承外层 this
箭头函数会自动继承外层函数的 this 指向,这样就能正确访问到 $bus:
import Vue from 'vue'; export default function (_ctx, inject) { const notify = function (msg) { console.log('emitting', msg); // 箭头函数继承外层notify函数的this setInterval(() => { this.$bus.$emit('add', msg); }, 500); }.bind(new Vue()); inject('notify', notify); }
方案3:提前缓存 bus 实例
在 notify 函数里把 $bus 存到变量中,避免回调里的 this 混乱:
import Vue from 'vue'; export default function (_ctx, inject) { const notify = function (msg) { console.log('emitting', msg); // 提前缓存bus实例 const eventBus = this.$bus; setInterval(() => { eventBus.$emit('add', msg); }, 500); }.bind(new Vue()); inject('notify', notify); }
额外注意事项
- 定时器重复创建问题:每次调用
this.$notify()都会新建一个setInterval,如果多次调用会导致多个定时器同时运行,建议:- 如果是一次性通知,把
setInterval换成setTimeout; - 如果需要持续触发,记得保存定时器 ID,提供清除方法避免内存泄漏。
- 如果是一次性通知,把
- 调试小技巧:可以在
$emit前打印this.$bus,确认它是正确的 Vue 实例;也可以用 Vue Devtools 查看事件总线的监听列表,确认组件的$on是否成功注册。
内容的提问来源于stack exchange,提问作者Simeon Aleksov
相关产品推荐
相关产品推荐

