Vuejs2 Vue.js方法在只应调用一次时,使用$emit和$on多次调用

Vuejs2 Vue.js方法在只应调用一次时,使用$emit和$on多次调用,vuejs2,vue-component,vue.js,Vuejs2,Vue Component,Vue.js,我使用总线允许组件通过此链接中描述的方法与其他组件交互: 我有一个在created hook中调用的方法,它使用总线发出事件 created () { this.getReviewDeck() }, myMethod () { bus.$emit('increment') } 在另一个组件(包含在上述组件中)中,我将事件侦听器连接到创建的钩子中,如下所示: created () { bus.$on('increment', this.incrementCount) }, inc

我使用总线允许组件通过此链接中描述的方法与其他组件交互:

我有一个在created hook中调用的方法,它使用总线发出事件

created () {
  this.getReviewDeck()
},
myMethod () {
    bus.$emit('increment')
}
在另一个组件(包含在上述组件中)中,我将事件侦听器连接到创建的钩子中,如下所示:

created () {
  bus.$on('increment', this.incrementCount)
},
incrementCount () {
  console.log('count incremented')
}
如果我第一次访问组件时一切正常,控制台将记录一次“count incremented”。但是,如果我离开该组件,然后导航回该组件,则下次“计数递增”将记录两次,如果我离开并再次返回,则现在将记录三次,以此类推


我不太清楚到底发生了什么,也不知道如何最好地解决这个问题,因此每次我转到组件时,消息只记录一次而不是多次。

必须在销毁时删除事件处理程序

 beforeDestroy () {
    EventBus.$off('increment', this.incrementCount)
 },
您可以使用$。一次

created () {
  bus.$once('increment', this.incrementCount)
},

如果您希望在事件发出后仅执行一次操作,则此选项适用。如果您想继续侦听事件,例如:如果您将鼠标悬停在图形上的某个数据点上,您想触发其他组件的某些操作,该怎么办。 在这种情况下,使用$once不起作用。 我面临着同样的问题,当我在悬停时发出一个事件并使用$on订阅它时,它应该只被调用一次,但在我的情况下,它会被调用多次

这就是我发出事件的方式

this.$eventBus.$emit("SHOW_HOVERLINE", d);
this.$eventBus.$on("SHOW_HOVERLINE", this.someFunction);
这就是我订阅活动的方式

this.$eventBus.$emit("SHOW_HOVERLINE", d);
this.$eventBus.$on("SHOW_HOVERLINE", this.someFunction);

我有一个类似的问题,上面提到的答案都不适合我。 我通过将eventBus添加为Vue全局实例解决了这个问题

将其添加到main.js文件中

Vue.prototype.$bus = new Vue();
并在组件中调用它,如:

   mounted(){
    this.$bus.$on('chatData', (data) => {
        console.log('receieved in component');
    });
   },
   beforeDestroy() {
    this.$bus.$off('chatData');
   },
   methods:{
    sendData(data){
     this.$bus.$emit('someData',data); 
    }
   }

要删除所有侦听器,请执行以下操作:

this.$eventBus.$off()
将此添加到主组件生命周期的beforeDestroy()事件中

beforeDestroy() {
   this.$bus.$off('chatData');
}

在Vue源代码中似乎发生了一些变化,因为在destroyed或beforeDestroy或BeforeRouteAve或任何其他钩子中关闭eventBus侦听器会执行以下操作-旧侦听器与在创建的钩子中重新注册的新侦听器一起被删除

对于destroyed和beforeDestroy钩子,这是可以理解的,因为它们在创建钩子之后被称为。所以created()添加监听器,destromed()删除所有监听器,而不仅仅是以前创建的()中的监听器。但是对于路由钩子,我不理解它们的行为,因为它们是在created()之前调用的,但是所有重新注册的侦听器都不起作用

我所做的是在重新注册之前关闭created hook中的eventBus侦听器

created() {
  eventBus.$off("someListener");
  eventBus.$on("someListener", () => {
    // do smth
  })
}

但这只有在重新创建组件时才有效,在应用程序生命周期中只创建一次,注册的侦听器将无法工作。但是如果组件创建一次,我们就不需要重新注册。

如何设置总线?也许你多次定义它?我通常在应用程序的引导过程中将总线添加到Vue组件原型中。这将确保您不会多次定义它。作为第一个“调试步骤”,您应该在创建的方法中进行控制台日志记录,在该方法中注册总线,以检查调用该方法的频率。应该只调用一次。您所说的“离开/访问组件”是什么意思?在我的情况下,@dpst的解决方案工作不太好,在我添加
总线时,它触发了三次固定值。在删除之前,$off
。此时,我只是在函数末尾添加了
bus.$off
,并将其命名为一天。在我自己的项目中,我使用了
销毁
事件,而不是
销毁前
。我认为此链接上的帖子应该与此答案一起阅读。这是对重复事件侦听器问题的一个很好的解释(为了更好地理解):如果您有新问题,请单击按钮提问。如果此问题有助于提供上下文,请包含指向此问题的链接。-当然我会把这个作为一个问题来补充,这对我来说也很有效。虽然上述解决方案是正确的,但在我的情况下,我没有离开组件,因此beforeDestroy不相关,事件仍会触发两次或更多次…那么你没有关闭事件吗?如你所述,将事件添加为Vue全局实例有助于我在我的组件中触发两次事件,因为我没有离开它。。。但当最终组件被留下时,仍然在销毁之前关闭它们。。。