局部页面关闭触发事件_给你代码:小程序页面间消息订阅及触发原理的实现

a6c1aaf43386325597cda6e469ba9c50.png

我们先想想这样很常见的应用场景:你正在浏览自己的一篇博客,发现有瑕疵,就点击编辑按钮打开了一个新页面,确认更新后当前页面被关闭,然后博客展示页上的内容也自动更新了,那么问题来了:怎么告诉博客展示页,这篇博客有更新,需要刷新数据呢?

暴力不推荐的方案

在Page()实例中,有个生命周期回调函数:onShow(),每当页面展示在最上层时,总会执行此方法。那么我们就可以把获取博客内容的操作放在这里:

Page({  data: {    blog: null  }  onShow() {    fetch('path/to/blog?id=1').then(blog => this.setData({blog: blog}));  }});

所以当编辑页面被关闭后,会触发调用博客展示页的onShow(),实现数据的重新获取。但是假设我们误点了编辑按钮,啥也没干又返回了,会有什么问题?问题倒是没有,但是会再次发起一次不必要的数据请求,不是吗?因为我们并没有更新博客,造成了资源浪费。我们需要有更好的解决方案:确切的知道博客被编辑了这个事件,然后再去做数据请求,也就是所谓的按需加载。

消息订阅机制

先来看代码吧:

//app.jsApp({   data: {    subscribes: {      'BLOG_UPDATED': [], // 博客有更新      'ANOTHER_CHANGED': [], // 其他某某有变化    }  },  /**   * 消息订阅   * @param string subject 消息主题   * @param function callback 处理函数   * @return int 订阅句柄   */  subscribe(subject, callback) {    if (undefined === this.data.subscribes[subject]) return;    this.data.subscribes[subject].push(callback);    return this.data.subscribes[subject].length -1;  },  /**   * 消息发布   * @param string subject 消息主题   */  publish(subject) {    if (undefined === this.data.subscribes[subject]) return;    this.data.subscribes[subject].forEach(callback => 'function' == typeof callback && callback());  }   /**   * 取消订阅   * @param string $subject 消息主题   * @param int flag 订阅句柄   * @param return void   */  unsubscribe(subject, flag) {    if(this.data.subscribes[subject] && this.data.subscribes[subject][$flag]) {      this.data.subscribes[subject][$flag] = null;    }  }});

我们在app.js中定义了订阅事件列表subscribes和了三个方法:

  • subscribe(subject, callback)
  • publish(subject)
  • unsubscribe(subject, flag)

首先介绍一下subscribes的格式:subscribes被定义成一个包含一系列键值对的对象,每个键代表我们的业务更新事件,值代表订阅者的事件处理方法列表。

subscribe(subject, callback)

消息订阅函数,需提供要订阅的主题和回调方法。我们还是以博客为例,假设博客详情页路径为:blog/detail(以pages目录为基准),博客编辑页为:blog/edit。在blog/detail的脚本文件中,加入以下代码:

Page({  data: {    flag: null  },  onReady() {    let flag = getApp().subscribe('BLOG_UPDATED', () => {      // 重新获取博客数据,例如:      // fetch('path/to/blog?id=1').then(blog => this.setData({blog: blog}));    });    this.setData({flag: flag});  }})

我们在onLoad()方法也即页面加载的时候加入订阅处理事件,并保存回调处理标识,后续需要用到。这样我们就完成了对博客更新动作的监听。接下来我们需要用publish函数对更新操作发起广播通知。

publish(subject)

在blog/edit脚本文件中,我们应该在编辑完成后调用此函数发布主题变更通知,交由app.js处理订阅方法列表:

Page({  update() {    fetch('path/to/blog/update?id=1').then(() => {      getApp().publish('BLOG_UPDATED');    });  }})

因为还要考虑到页面被销毁的情况,当页面不存在时,如果其他页面仍然触发了订阅事件,app.js在执行订阅处理方法列表时势必会出错,所以我们需要在订阅的同时也要明确指定什么时候取消订阅。我们在blog/detail脚本中再增加以下代码:

unload() {  getApp().unsubscribe('BLOG_UPDATED', this.data.flag);}

这样当blog/detail页面被卸载后,其订阅的处理方法也随之被取消。

总结

在使用这套消息订阅发布机制后,页面间的无感更新体验会变得非常棒,通常你还在当前页面做了更新,由于页面回退和关闭会有一段很小的动画效果,此时其他页面的数据更新已经完成了,当被层叠的页面再次出现时,数据已然是最新的了。


给你代码往期回顾:

给你代码:leetcode随笔

暴走状态!小程序用户UnionID的获取及登录状态维护——给你代码

给你代码:leetcode题目加小技巧

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值