小程序页面onLoad时redirectTo其它页面,如何优雅的阻止onShow执行?

7,395 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第27天,点击查看活动详情

背景

有时候,我们需要在小程序的onLoad生命周期做一些校验,若校验不通过,则wx.redirectTo其它页面。

但是,如果直接在onLoad里面执行wx.redirectTo,那么小程序还是会执行完本页面的onShowonUnload,才会关闭本页面。

其实大部分时候,如果你马上要切走页面了,onShowonUnload没必要执行,执行太多只会影响你页面切换的速度,而且一些场景下还会引入Bug。

所以,我们需要一种优雅的方式,阻止onShowonUnload执行。

一种解决方案

在本页面设置一个变量:preventOnShow,默认为false,如果需要阻止onShow,就设置为true。在onShow逻辑中,优先判断preventOnShow,如果为true,就直接return。注意preventOnShow不要放在data里面,因为它不需要渲染,更新它时不影响wxml。

代码如下:

Page(
  data: {},
  preventOnShow: false,
  onLoad(options) {
    // 如果发生特殊情况,就直接redirectTo其它页面
    if (...) {
      this.preventOnShow = true;
      wx.redirectTo({ url: '...' });
      return;
    }
    // ... 其它onLoad逻辑
  },
  onShow() {
    if (this.preventOnShow) return;
    // ... 其它onShow逻辑
  },
);

更优雅的解决方案

为什么需要更优雅的解决方案?

因为上面的解决方案还不够好。我们需要在每个页面都加这样的重复逻辑:

Page(
  preventOnShow: false,
  onShow() {
    if (this.preventOnShow) return;
    // ... 其它onShow逻辑
  },
);

一旦某个页面忘记加,那么preventOnShow就失效了。

因此,我们最好通过某种方式一次性全局加上这种逻辑,避免开发者新建某页面时忘记,减少了出错率。这体现了工程化的思想。

具体怎么做?参考文章:《如何全局重写小程序 Page函数 wx对象?》

function onShowProxy(onShow) {
  return function newOnShow() {
    if (this.preventOnShow) return;
    if (onShow) {
      return onShow.call(this);
    }
  };
}

function pageProxy(Page: WechatMiniprogram.Page.Constructor): WechatMiniprogram.Page.Constructor {
  return function newPage(options) {
    Page({
      ...options,
      preventOnShow: false,
      onShow: onShowProxy(options.onShow),
    });
  };
}

Page = pageProxy(Page);

以上逻辑,在app.js中引入即可。

这样,我们就一次性给所有页面加上了preventOnShow属性,通过给它赋值true,即可跳过执行onShow

写在最后

我是HullQin,公众号线下聚会游戏的作者(欢迎关注公众号,联系我,交个朋友),转发本文前需获得作者HullQin授权。我独立开发了《联机桌游合集》,是个网页,可以很方便的跟朋友联机玩斗地主、五子棋等游戏,不收费无广告。还独立开发了《合成大西瓜重制版》。还开发了《Dice Crush》参加Game Jam 2022。喜欢可以关注我噢~我有空了会分享做游戏的相关技术,会在这2个专栏里分享:《教你做小游戏》《极致用户体验》