vue中eventbus被多次触发(vue中使用eventbus踩过的坑)

一开始的需求是这样子的,我为了实现两个页面组件之间的数据传递,假设我有页面A,点击页面A上的某一个按钮之后,页面会自动跳转到页面B,同时我希望将页面A上的某一些参数携带过去给页面B。(我知道,小参数的时候可以通过路由的params或者query去传参数,或者大型数据可以用vuex来处理,很遗憾我到现在还没有做很大型的项目,所以还没有用过vuex,接下来会学习一下。)

然后我就想,这不就是不同组件之间的数据传递问题而已吗?直接用bus 巴士事件来传递数据不就行了吗。于是,我就很愉快地进行了。关于vue中的eventbus的使用,我之前在一篇vue中的数据传递中有提到过…

先给你们看一下我一开始的代码:

实现目标: 
点击之后,bus emit事件,然后顺便跳转路由到/moneyRecord页面。
接下来就是在MoneyRecord页面中去on接收这个事件,然后接受参数。
// 这是页面A的内部触发bus事件的代码
editList (index, date, item) {
  // 点击进入编辑的页面,需要传递的参数比较多。
  console.log(index, date, item)
  bus.$emit('get', {
    item: item.type,
    date: date
  })
  this.$router.replace({path: '/moneyRecord'})
}

// moneyRecord页面
created () {
  //这里我将icon的list给保存下来了
  bus.$on('get', this.myhandle)
},
methods: {
  myhandle (val) {
    console.log(val, '这是从上个页面传递过来的参数')
  }
}
就当我欣喜若狂的时候,觉得自己只要在页面A触发了get事件,页面B中就会理所当然的接受了数据。然而,结果却不如人意,看一下下面的动图。
主要是看这是从上个页面传来的数据这一行数据的输出次数情况来判断事件触发次数

在这里插入图片描述

不知道你有没有发现,就是我第一次进去list页面的时候,我随便点击一下list下的任何一个item,控制台没有输出。但是当我第二次再点击触发事件的时候,就会输出一个测试数据。再一次进去点击,就输出两个数据。。。依次增加了。(控制台上那个“这是从上个页面传来的数据”就是测试数据)

问题:

  • 问题1: 为什么第一次触发的时候页面B中的on事件没有被触发?
  • 问题2: 为什么后面再一次依次去触发的时候会出现,每一次都会发现好像之前的on事件分发都没有被撤销一样,导致每一次的事件触发执行越来越多?

解决:

  • 针对问题1
    这个还得从vue的生命周期说起了,我先进行了测试,就是当从页面组件A跳转到页面组件B的时候,两个组件的生命周期分别是怎么样的,关于vue的生命周期具体每一个时期做什么事情我就不再赘述了,下面po一张vue生命周期的图。

在这里插入图片描述

我自己做了实验来验证,这个页面跳转过程中,这两个组件的生命周期的执行情况。

// 我分别在页面A和页面B中去添加以下代码:
beforeCreate () {
   console.group('%c%s', 'color:red', 'beforeCreate 创建前状态===============组件2》')
 },
 created () {
   console.group('%c%s', 'color:red', 'created 创建完毕状态===============组件2》')
 },
 beforeMount () {
   console.group('%c%s', 'color:red', 'beforeMount 挂载前状态===============组件2》')
 },
 mounted () {
   console.group('%c%s', 'color:red', 'mounted 挂载状态===============组件2》')
 },
 beforeUpdate () {
   console.group('%c%s', 'color:red', 'beforeUpdate 更新前状态===============组件2》')
 },
 updated () {
   console.group('%c%s', 'color:red', 'updated 更新状态===============组件2》')
 },
 beforeDestroy () {
   console.group('%c%s', 'color:red', 'beforeDestroy 破前状态===============组件2》')
 },
 destroyed () {
   console.group('%c%s', 'color:red', 'destroyed 破坏状态===============组件2》')
 }
// 另外一个组件的我就不放出来了

测试结果图:
在这里插入图片描述
在这里插入图片描述

其实,可以通过结果清楚看到,当我们还在页面A的时候,页面B还没生成,也就是页面B中的 created 中所监听的来自于A中的事件还没有被触发。这个时候当你A中 emit事件 的时候,B其实是没有监听到的。
再看一下,红色的是B页面组件,当你从页面A到页面B跳转的时候,发生了什么?首先是先B组件先 created 然后 beforeMount 接着A组件才被销毁,A组件才执行 beforeDestory ,以及 destoryed
所以,我们可以把A页面组件中的emit事件写在 beforeDestory 中去。因为这个时候,B页面组件已经被 created 了,也就是我们写的 $on 事件已经触发了

所以可以,在 beforeDestory 的时候,$emit事件

// 修改一下A页面中的代码:
// 这是原先的代码
editList (index, date, item) {
  //  点击进入编辑的页面,需要传递的参数比较多。
  console.log(index, date, item)
  this.item = item.type
  this.date = date
  this.$router.replace({path: '/moneyRecord'})
}
// 重新在data属性内部定义新的变量,来存储要传过去的数据;
然后:
beforeDestroy () {
 console.log(this.highlight, '这是今年的数据', this, '看看组件销毁之前会发生什么')
 bus.$emit('get', {
  item: this.item,
   date: this.date
 })
},

接下来。看一下修改之后的效果
在这里插入图片描述

可以看到,就是第一次点击list的时候,也就是第一次触发 emit事件 的时候,控制太就输出了,所以在 beforeDestoryed$emit 是起到作用的,B页面组件也 监听$on 到了。
但是,好像,就是事件的触发还是会依次增加,就是控制台的输出每次都有所增加了…

解决:
看一下github上提出的。issue https://github.com/vuejs/vue/issues/3399

在这里插入图片描述
尤大大提出了以下解决:
在这里插入图片描述

就是说,这个 $on事件 是不会自动清楚销毁的,需要我们手动来销毁。(不过我不太清楚这里的 external bus 是什么意思,有大神能解答一下的吗,尤大大也提到如果是注册的是 external bus 的时候需要清除)

所以。我在B组件页面中添加 Bus.$off 来关闭。代码如下:

// 在B组件页面中添加以下语句,在组件beforeDestory的时候销毁。
  beforeDestroy () {
    bus.$off('get', this.myhandle)
  },

来看一下输出的结果:
请添加图片描述

当然,尤大大还说可以写一个mixin?我还不知道是什么?以后在研究一下。

总结: 所以,如果想要用bus 来进行页面组件之间的数据传递,需要注意亮点,组件A $emit事件 应在 beforeDestory 生命周期内。其次,组件B内的 $on 记得要销毁。


提问时间:你们在实现页面组件之间的数据传递有什么好的方法吗?可以留言分享一下吗?有时候虽然也可以通过从后台获取,但是考虑到数据只有几个需要传的话,就没有必要去请求数据,我知道有的还有用vuex传递和路由带参传递,还有呢?

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 14
    评论
VueEventBus是一个全局事件总线,用于在组件之间进行通信。通过EventBus,我们可以在一个组件触发事件,并在其他组件监听和处理这些事件。引用\[1\]的代码演示了如何在Vue使用EventBus进行事件监听和移除。首先,我们需要导入EventBus,然后定义一个事件监听函数。使用EventBus.$on()方法来监听一个自定义事件,并将事件名称和监听函数作为参数传递进去。当事件被触发时,监听函数将被执行。要停止监听事件,可以使用EventBus.$off()方法,并传递事件名称和监听函数作为参数。这将移除指定事件的指定监听函数。引用\[2\]提到了在业务有反复操作的页面时,EventBus可能会触发多次事件,这可能会导致问题。为了解决这个问题,可以在Vue页面销毁时,同时移除EventBus的事件监听。引用\[3\]展示了在接收方组件如何使用EventBus.$on()方法订阅自定义事件并处理其响应。在mounted钩子函数使用EventBus.$on()方法来订阅自定义事件,并将处理函数作为参数传递进去。当事件被触发时,处理函数将被执行。 #### 引用[.reference_title] - *1* *2* [vue - EventBus](https://blog.csdn.net/qq_39085060/article/details/104226440)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [Vue的Event Bus](https://blog.csdn.net/AlegFox/article/details/130282307)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值