宏观上,微信小程序是由一个个 Page 组成的。有时候我们会遇到一些业务存在耦合的 Page,一个 Page 里某个状态改变后,相关 Page 的状态需要进行更新。而在小程序里,每个 Page 都是一个模块,有着独立的作用域,因此 Page 间需要有一种通信策略。

想象一个业务场景,用户首先进入订单列表页。然后点击其中一个订单,进入到订单详情页。当用户在订单详情页对订单进行操作,例如支付、确认收货等时,该订单的状态就会发生改变。此时需要对上一级的订单列表页中该订单的状态进行更新:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-N3r2ke3t-1633676887031)(006tNc79gy1g58ypytisrj30mx0hiq3n.jpg)]

要想更新订单列表页的视图层,就需要调用该 Page 对象的 setData 方法。这里为大家列举三种比较常用的方案:

设置标志位

最简单的方法,在订单详情页对订单的操作成功回调中,把一些标志位设置为 true,并设置好参数(标志位和参数可以存在 localStorage 或挂在全局 App 对象下)。然后每次在订单列表页的 onShow 生命周期中,根据这些标志位去判断是否进行更新、更新的参数是什么。

这种处理在业务逻辑比较简单、页面间的耦合度很小时还能凑合,一旦逻辑复杂起来,就需要写很多冗余的代码,并且维护成本会非常高。

流程图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Wwqb4Bfk-1633676887032)(006tNc79gy1g58yrl4qf3j30nr0l0jt2.jpg)]

利用页面栈获取 Page 对象

如果订单详情页里能拿到订单列表页的 Page 对象,就能去调用它的 setData 方法。小程序提供了一个方法 getCurrentPages,执行它可以得到当前页面栈的实例,然后再根据页面进栈的顺序我们就能拿到订单列表页的 Page 对象。

然而这种做法的缺点还是耦合度太大,过度依赖页面进栈顺序。一旦在以后的产品迭代中页面顺序发生变化,将很难去维护。

流程图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7fJJsGeX-1633676887032)(006tNc79gy1g58ysf06w8j30nr0mo402.jpg)]

上述两种方法都存在着耦合度大、维护困难的问题,而利用发布/订阅模式能很好的实现解耦,下面我们先来了解一下这种设计模式。

发布/订阅模式(最优方案)

发布/订阅模式由一个发布者、多个订阅者以及一个调度中心所组成。订阅者们先在调度中心订阅某一事件并注册相应的回调函数,当某一时刻发布者发布了一个事件,调度中心会取出订阅了该事件的订阅者们所注册的回调函数来执行。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hbo8xVC2-1633676887033)(006tNc79gy1g58ytf9fgaj30es0aj3yv.jpg)]

在发布/订阅模式中,订阅者和发布者并不需要关心对方的状态,订阅者只管订阅事件并注册回调、发布者只管发布事件,其余一切交给调度中心来调度,从而能实现解耦。

在 app 跨页面通信这个问题上,iOS 端的 Notification Center、安卓端的 EventBus,也是通过这样一种设计模式去解决的,不过微信小程序内部并没有提供这种事件通知机制,所以我们需要手动去实现一个。

我们首先要实现一个 Event 类,它应该含有一个收集回调函数的对象,和提供三个基础方法:on(订阅)、 emit(发布)、 off(注销)。

//event.js
class Event {on (event, fn, ctx) {if (typeof fn != "function") {console.error('fn must be a function')return}this._stores = this._stores '' {};(this._stores[event] = this._stores[event] '' []).push({cb: fn, ctx: ctx})}emit (event) {this._stores = this._stores '' {}var store = this._stores[event], argsif (store) {store = store.slice(0)args = [].slice.call(arguments, 1)for (var i = 0, len = store.length; i < len; i++) {store[i].cb.apply(store[i].ctx, args)}}}off (event, fn) {this._stores = this._stores '' {}// allif (!arguments.length) {this._stores = {}return}// specific eventvar store = this._stores[event]if (!store) return// remove all handlersif (arguments.length === 1) {delete this._stores[event]return }// remove specific handlervar cbfor (var i = 0, len = store.length; i < len; i++) {cb = store[i].cbif (cb === fn) {store.splice(i, 1)break}}return}
}

具体调用方法

App 是小程序的实例,在每个 Page 里都能通过执行 getApp 函数获取到它。我们可以把 Event 类的实例挂载在 App 中,方便每个 Page 去调用。

// app.jsconst Event = require('./libs/event')App({event: new Event()
})

订单列表页在 onLoad 生命周期中订阅 “afterPaySuccess” 事件。

//order_list.jsvar app = getApp()Page({onLoad: function(){app.event.on('afterPaySuccess', this.afterPaySuccess, this)},afterPaySuccess: function(orderId) {},
})

在订单详情页支付成功的回调中,发布 “afterPaySuccess” 事件,同时带上订单 id 参数

//order_detail.jsvar app = getApp()Page({raisePayment: function() {app.event.emit('afterPaySuccess', orderId)}
})

所有 Page 的 onUnload 生命周期,必须注销掉之前订阅的事件。注销方法 off 的调用姿势有三种,不过还是建议注销当前 Page 所订阅的事件,而不是注销所有的。

var app = getApp()Page({onUnload: function(){// remove allapp.event.off()// remove all callbacksapp.event.off('afterPaySuccess')// remove specific callbacksapp.event.off('afterPaySuccess', this.afterPaySuccess)}
})

微信小程序跨页面通信解决思路相关推荐

  1. 微信小程序跨页面通信

    简单业务场景,比如用户中心进入修改手机号页面,修改成功后用户中心需要立马调用setData来修改显示数据,最优的方法是使用发布/订阅模式 创建Event类,event.js class Event { ...

  2. 微信小程序模板消息群发解决思路

    基于微信的通知渠道,微信为开发者提供了可以高效触达用户的模板消息能力,以便实现服务的闭环并提供更佳的体验.(微信6.5.2及以上版本支持模板功能.低于该版本将无法收到模板消息.) 模板推送位置:服务通 ...

  3. 2021-09-15核芯物联推荐生态合作伙伴莱讯科技#蓝牙AoA微信小程序跨楼层高精度定位导航,支持ibeacon+aoa融合,完美解决ibeacon导航存在的覆盖盲区

    2021-09-15核芯物联推荐生态合作伙伴莱讯科技#蓝牙AoA微信小程序跨楼层高精度定位导航,支持ibeacon+aoa融合,完美解决ibeacon导航存在的覆盖盲区 核芯物联推荐生态合作伙伴莱讯科 ...

  4. 微信小程序中使用全局变量解决页面的传值问题

    微信小程序中使用全局变量解决页面的传值问题 由于项目需要,最近便在做 一个类似于美团的餐饮平台的的微信微信小程序 ,项目有十几个页面,那么页面间的传值被经常用到.在小程序中页面间的传值主要有使用全局变 ...

  5. 微信小程序页面栈_微信小程序之页面传值(路由、页面栈、globalData、缓存)

    1. 通过url带参数传递 1.1 固定参数传递 例如,从 list 页面到 detail 页面, 传递一个或多个固定值 list页面传值: 点此进入 detail detail页面取值: onLoa ...

  6. 微信小程序tabar页面不触发onShow

    微信小程序tabar页面不触发onShow [场景]: 开发中,原本js里面没有onShow方法,后面加上了onShow, 除了第一次页面加载调用了onShow方法,之后切换页面都没有触发. [解决办 ...

  7. 微信小程序开发-页面跳转传递参数

    微信小程序开发-页面跳转传递参数 页面跳转有四种方式,分别为wx.navigateTo.wx.redirectTo.wx.reLaunch.wx.switchTab,前面三种可通过url路径携带参数实 ...

  8. 标题微信小程序提示页面未注册问题解决

    标题微信小程序提示页面未注册问题解决 1.出现的问题 在WXML部分编译完成后页面可以正常显示样式,然而在.js文件编辑完成后进行编译时会出现如下错误提示: 2.出现的原因及解决方法 .JS文件中缺少 ...

  9. 微信小程序禁止页面左右滑动

    微信小程序禁止页面左右滑动 小程序禁止页面左右滑动 PS:在开发过程中可能会遇到某一个页面可以左右滑动,在开发者工具是查看不出来,只有在手机预览才可以看的出来(尝试左或者右滑动). 我的解决方法是在根 ...

最新文章

  1. Boosting和Bagging: 如何开发一个鲁棒的机器学习算法
  2. Nature子刊:吃得越少,活得越久
  3. Linux初学时的一些常用命令(4)
  4. 动环监控系统接线图_机房动环监控系统报价
  5. SharePoint 2013让页面显示错误
  6. SDL_gfx-2.0.23在windows平台下的编译及例子
  7. 计算Linux内存,CUP,硬盘使用率的shell脚本
  8. c语言中如何用字母代替加减乘除的符号,c语言加减乘除代码
  9. php中数组自定义排序
  10. python支持双向索引_python3 deque 双向队列创建与使用方法分析
  11. Apple和Ruby近况:Rails的iPhone配置实用工具和Ruby的SproutCore工具
  12. 英文邮件开场白(Dear / Hi / TO)
  13. 【大数据】大数据技术框架,有这一篇文章就够了
  14. Android 版本4.12 微信,安卓4.12微信下载
  15. CSS简单的图片居中
  16. SHON WEBB:坚持做这四件事,会让你的自律达到新的高度
  17. chrome 常用插件下载安装
  18. 【猿说VUE】Vue列表渲染
  19. 【译】Sobel 算子文档
  20. spark-2.2.0发行说明

热门文章

  1. 胶原蛋白肽-透明质酸负载表皮生长因子水凝胶EGF-CP-HA/接枝NgR抗体的透明质酸水凝胶
  2. 神仙级Python入门教程(非常详细),从零基础入门到精通,从看这篇开始
  3. 运筹说 第39期 | 运输问题经典例题讲解
  4. ug西门子840d后处理教程_UG 后处理视频教程 五轴制作发那科西门子海德汉
  5. 3d游戏建模制作流程详解 丨漫威宇宙【万磁王】
  6. 【MAMP】macOS下使用MAMP的php环境版本配置方法
  7. 解决eclipse复制代码到word中出现底色问题
  8. 普陀区委组织部领导一行调研上海控安
  9. [2016.10.17日更新]各大互联网公司架构演进之路汇总
  10. js定时触发-----新订单提醒展示效果并提示音效