资讯详情

微信小程序跨页面通信解决思路

从宏观上讲,微信小程序是由一个个组成的 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], args          if (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 '' {}          // all         if (!arguments.length) {             this._stores = {}             return         }          // specific event         var store = this._stores[event]         if (!store) return          // remove all handlers         if (arguments.length === 1) {             delete this._stores[event]             return          }          // remove specific handler         var cb         for (var i = 0, len = store.length; i < len; i  ) {             cb = store[i].cb             if (cb === fn) {                 store.splice(i, 1)                 break             }         }         return     }    } 

具体调用方法

App 它是每个小程序的例子 Page 可以在里面执行 getApp 获得函数。 Event 类实例挂载在 App 每一个都方便 Page 去调用。

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

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

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

在订单详细信息页付成功回调 “afterPaySuccess” 同时带上订单 id 参数

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

所有 Page 的 onUnload 生命周期必须取消以前订阅的事件。取消方法 off 有三种调用姿势,但建议取消目前的调用姿势 Page 所订阅的事件,而不是注销所有的。

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

标签: bfk系列通用继电器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

 锐单商城 - 一站式电子元器件采购平台  

 深圳锐单电子有限公司