mpvue小程序迁移为uniapp项目A(用于标识项目),同时编译部署微信小程序和微信服务号H5

问题描述

页面刷新时会导致vuex内状态失效,但不准备在页面刷新前将vuex备份到localStorage等临时存储方式

由于小程序使用开发者工具刷新时会回到项目首页(pages 中的第一个索引),于是将H5交互保持与小程序一致,使用微信内置刷新时项目跳转回首页。

处理方式为:

在 App.vue 的onLaunch(项目生命周期)中增加以下逻辑

// #ifdef H5
const visit = sessionStorage.getItem("appvue");
if (visit === "true") {
  wx.reLaunch({
    url: "/pages/home/home",
  });
} else {
  sessionStorage.setItem("appvue", true);
}
// #endif

代码解释:

条件编译控制此逻辑仅在 H5 编译方式下生效

使用sessionStorage判断页面是否在进行刷新操作(在一次会话中,第一次进入项目时存储一个状态appvue,当使用微信浏览器内置刷新操作时,会话未过时,但项目会重新触发项目生命周期onLaunch,此时发现sessionStorage中包含appvue的状态,则执行页面跳回首页的交互)

但项目中存在webview组件

当项目中某个页面通过webview组件打开部署在另一个地方的H5项目 B 页面时,存在以下交互:

B (webview)某页面点击按钮跳转到 A (小程序/H5)的页面,点击返回,会直接以访问 A 项目公网地址的方式进行跳转(类似https://www.xxx.com/A

此时跳回 A 会触发项目 AApp.vue 中的 onLaunch (项目生命周期)执行,但会话未过时,会触发跳转首页的逻辑,导致因为从 webview 跳转到项目 A 而跳回项目首页,而不是指定的路由,故存在问题。

解决方案

方案一

webview 组件加载时去掉 sessionStorage 中的标识,这样当从 webview 访问项目 A 时不会刷新回首页

web-view.vue

onLoad(query) {
    this.url = decodeURIComponent(query.url)
    const visit = sessionStorage.getItem('appvue');
    if (visit === 'true') {
      sessionStorage.removeItem('appvue');
    }
}

App.vue

onLaunch(e) {
  // #ifdef H5
  const visit = sessionStorage.getItem('appvue');
  if (visit === 'true') {
      wx.reLaunch({
        url: '/pages/home/home'
      });
  } else {
    sessionStorage.setItem('appvue', true);
  }
  // #endif
}

方案问题

webview 访问项目 AApp.vue 执行 onLaunch 时不会跳转首页,但会记录 appvue ,此时页面返回到 webview 后再次进入,sessionStorage 检测到 appvue 有值,则仅第一次进入 A 时不会跳转首页,返回再进入时还是会跳转

方案二

维护一个白名单,内容是在 webview 中访问的 A 项目路由,放行不进行跳转首页

App.vue

methods: {
  /**
    * 是否是从webview进行跳转的页面
    * @return 是否进行跳转
    */
  pagesFromWebview(e) {
    let skipFlag = false;
    // 维护白名单控制在webview中访问的页面不做回到首页的跳转
    const notFreshPages = [
      'iou-reason',
      'upload-reason-imgs',
      'info-fill',
      'iou-info',
    ];
    if (e && e.path) {
      const list = e.path.split('/');
      if (list && list.length > 0) {
        // 取最后一个作为路由标识
        const flag = list[list.length - 1];
        console.log('==========flag: ' + flag);
        // 如果该路由在不刷新的名单中则不进行回到首页的跳转
        if (notFreshPages.includes(flag)) {
          skipFlag = true;
        }
      }
    }
    return skipFlag
  }
},

onLaunch(e) {
  // #ifdef H5
  const visit = sessionStorage.getItem('appvue');
  // TODO: 弃用维护白名单的方式,改用更好的方式
  if (visit === 'true' && !this.pagesFromWebview(e)) {
      wx.reLaunch({
        url: '/pages/home/home'
      });
  } else {
    sessionStorage.setItem('appvue', true);
  }
  // #endif
}

方案问题:需要维护白名单,当白名单内的路由变更时可能会因为遗漏维护而导致问题再次出现

方案三

弃用白名单,增加第二个 sessionStorage 状态,当进入 webview 时禁用跳回首页的开关,离开 webview 时关闭禁用

web-view.vue

onLoad(query) {
  this.url = decodeURIComponent(query.url)
  // 进入webview后禁止【页面刷新回首页】
  const notfresh = sessionStorage.getItem('notfresh');
  if (!notfresh) {
    sessionStorage.setItem('notfresh', true);
  }
},
onUnload() {
  // 从webview页返回到本项目时触发
  this.url = ''
  // 离开webview时解禁【页面刷新回首页】
  const notfresh = sessionStorage.getItem('notfresh');
  if (notfresh === 'true') {
    sessionStorage.removeItem('notfresh');
  }
},

App.vue

onLaunch(e) {
  // #ifdef H5
  const visit = sessionStorage.getItem('appvue');
  const notfresh = sessionStorage.getItem('notfresh');
  if (visit === 'true' && notfresh !== 'true') {
    wx.reLaunch({
      url: '/pages/home/home'
    });
  } else {
    sessionStorage.setItem('appvue', true);
  }
  // #endif
}

存在问题,无法对 webview 跳去的 A 项目页面做刷新后跳转首页的控制