遇到一个这样的业务需求, 用户点击提现按钮, 跳转到提现处理结果页面, 为了避免提现请求被重复提交, 所以需要在用户点击了提交按钮以后就把按钮锁起来不给用户提交, 在拿到请求结果以后再把按钮打开
先看界面
再看实现逻辑
onWithdraw () {
console.log('加锁', this.data.isWithdrawing)
if (this.data.isWithdrawing) return
// isWithdrawing要在data中初始化为false
this.data.isWithdrawing = true
console.log('按照预期, 这里在跳转之前应该只执行一次', this.data.isWithdrawing)
req.redpack.withdraw(this.data.withDrawAmount, this.data.currentCardId)
.then(res => {
// 请求参数不用看, 是封装的方法
if (res.code === 201) {
this.data.isWithdrawing = true
wx.navigateTo({
url: '/pages/redpack/withdrawResult/withdrawResult'
})
}
})
}
于是我输入金额, 疯狂的点击按钮, 看到的是这样的
难道应该把this.data.isWithdrawing = true
放在 wx.navigateTo后?于是测试, 无果(有兴趣的同学可以试试)
于是, 我打开了微信官方文档
噢...我懂了, this.data.isWithdrawing = true
应该放在complete回调里去支持, 于是我把代码改成这样:
测试
额......
由此我推断, complete回调是在页面跳转前执行的, 跳转前把锁解开, 然后我手速又比较快, 所以才出现了多次执行的情况, 那究竟要怎么处理呢?
再次翻阅文档, 一个event参数吸引了我, 但是官方写得有点模糊, 于是自己进行了代码的测试, 下面将我的理解分享给大家, 我喜欢用图形来表达, 请看图:
重点重点重点:
1) eventChannel是页面跳转时产生的一个独立于页面外的对象, 父页面和子页面都可以在eventChannel里面定义方法, 而eventChannel里面的方法在某种意义上是可以操作两个页面的数据的
2) 父页面通过events参数定义父方法一, 父方法二...
3) 子页面通过this.getOpenerEventChannel()
拿到eventChannel对象, 并且通过eventChannel.on来定义子方法一, 子方法二...
4) 父页面通过success或者complete里面的res拿到eventChannel对象, 并通过res.eventChannel.emit来触发子页面通过eventChannel.on定义的方法
5) 子页面通过this.getOpenerEventChannel()
拿到eventChannel对象执行emit来触发父页面定义的方法
6) 最后, 我所说的父方法, 子方法, 其实都是定义在eventChannel上的, 这样说只是方便大家理解, 父页面应该也也是可以通过emit去触发自己在events里面定义的方法的, 但是这样没有意义, 所以, 我就不做测试了,因为没有人会傻到自己跟自己通信吧, 哈哈哈...
再回到我们一开始的业务需求:
我们是不是可以这样操作, 在子页面显示的以后再去把父页面的锁打开呢?这样不就避免了重复提交的问题了吗?(当然有人会问我, 你为什么搞得这么复杂?直接锁死不就好了吗?但是你是够考虑到这样一种情况, 用户在提现以后, 又点击了后退页面, 再次进行提现, 这样你的锁还开着, 第二不就不能提现了吗?)
好了, 下面我们来实现代码
父页面:
子页面:
结果:
点返回, 再次提现
妥妥的....
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。