若你遇到的问题是在组件中使用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]
})
},
}
})