微信小程序+mitt事件库使用,事件被多次回调,页面卸载时取消监听off无效问题

若你遇到的问题是在组件中使用mitt事件总线的on回调this指向不正确,请转到解决微信小程序+mitt事件库在组件中this指向不正确问题-CSDN博客

2023-11-25 更新:

后来才想起来mitt库在on的第三个参数可以传入this!!! 此文章作废

原因: 

*小程序+mitt事件库一起使用的话,监听事件on时直接传入methods中的函数,函数被回调时,this是不正确的

 * 此时可以通过添加bind指定this来解决。

 *    例:emitter.on(LOGIN_SUCCESS, this.favorChangeCb.bind(this))

 * 但是这样的话如果页面重复onLoad,会发现事件会被添加多个监听函数,在事件触发时执行多次回调。

 * 原因是.bind(this)此操作会返回一个新的函数,也就代表着调用过bind的函数已经不是原来的函数了,他们的内存地址指向也不同了。

        this.test.bind(this) === this.test.bind(this) >> false

 * 这也就是为什么明明在onUnload中通过off取消监听了事件,但取消不掉,然后在某一时刻会多次触发的原因。

解决方案:

由于小程序中的this可以通过多种方法获取到。所以我的解决方案是不通过bind来绑定回调时的this。

方法一:通过getCurrentPages()函数获取当前页面的实例。

        但此方法有弊端,如果你再on回调时不处于这个事件本身的页面中。那么getCurrentPages获取到的页面实例就不会是事件被监听时本身所在的页面实例。而是你当前所处的页面实例。

        举个例子:再个人中心user页面点击退出登录,我希望首页监听到退出登录事件后做某些事情,那么此时首页通过getCurrentPages获取到的实例就不是首页,而是user页面。

test() {
  const that = getCurrentPages()[getCurrentPages().length - 1]
  console.log(that);
  that.setData({
    list:[1,2,3]
  })
},

方法二:如果是在组件中,希望获取组件实例,可以在全局设置一个变量。再组件/页面生命周期(attached/onLoad)中将组件的this赋值过去。这个方法就不会有方法一的弊端,其他弊端暂时未知

import { emitter } from "/app"

let that = null

Component({
  lifetimes:{
    attached(){
      that = this
      emitter.on('test',this.test)
    }
  },
  data: {

  },
  methods: {
    test() {
      console.log(that);
      that.setData({
        list:[1,2,3]
      })
    },
  }
})

  • 8
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Vue3中,官方建议使用外部的、实现了事件触发器接口的来实现事件总线的功能,而mitt是其中一个常用的选择。mitt是一个非常小巧的,只有200字节大小,并且支持全部事件监听和批量移除。它不依赖于Vue实例,可以在不同的框架或项目中使用,例如React、Vue甚至是jQuery项目都可以使用同一个mitt来实现事件总线的功能。在使用mitt,你需要先安装mitt(npm i mitt -s),然后可以通过mitt()创建一个mitt实例,并使用其提供的API来进行事件的绑定、触发和解绑操作。 下面是一些mitt的常用API: - `emit(name, data)`:触发事件,其中`name`是要触发事件名称,`data`是需要传递的参数。 - `on(name, callback)`:绑定事件,其中`name`是要绑定的事件名称,`callback`是触发事件后执行的回调函数。 - `off(name)`:解绑事件,其中`name`是需要解绑的事件名称。 在Vue3中使用mitt可以参考以下步骤: 1. 首先,你需要安装mitt(npm i mitt -s)。 2. 然后,在需要使用事件总线的组件中引入mitt,例如在你的`bb.vue`组件中,你可以使用`import bus from "../utils/EventBus"`来引入mitt。 3. 在需要发出事件的地方(例如点击按钮),可以使用`bus.emit("data", 18)`来触发名为"data"的事件,并传递参数18。 希望这个回答对你有帮助!如果你还有其他问题,请随提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值