IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> 微信小程序跨页面通信解决思路 -> 正文阅读

[移动开发]微信小程序跨页面通信解决思路

宏观上,微信小程序是由一个个 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)
    }
})
  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-10-09 16:23:57  更:2021-10-09 16:26:20 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 23:17:11-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码