天天看点

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

背景

有时候,我们需要在小程序的​

​onLoad​

​​生命周期做一些校验,若校验不通过,则​

​wx.redirectTo​

​其它页面。

但是,如果直接在​

​onLoad​

​​里面执行​

​wx.redirectTo​

​​,那么小程序还是会执行完本页面的​

​onShow​

​​和​

​onUnload​

​,才会关闭本页面。

其实大部分时候,如果你马上要切走页面了,​

​onShow​

​​和​

​onUnload​

​没必要执行,执行太多只会影响你页面切换的速度,而且一些场景下还会引入Bug。

所以,我们需要一种优雅的方式,阻止​

​onShow​

​​和​

​onUnload​

​执行。

一种解决方案

在本页面设置一个变量:​

​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);      

继续阅读