在H5页面中集成小程序的跳转路由
发布于 3 年前 作者 yongchen 314 次浏览 来自 分享

一.介绍

允许通过特定方式在H5页面集成小程序的路由,进行页面跳转,本篇文章H5已react react-router框架为例,大致流程如下:

首先需要提供一个判断H5当前运行环境的类(CommonEnv),对外只暴露CommonRouter类,CommonRouter类里面应集成各种应用渠道的路由跳转(如:浏览器,微信小程序),在H5页面的各个业务页面的路由跳转应只调用CommonRouter类上的方法

二.集成

  1. 创建CommonEnv类 用于判断运行环境:
export class CommonEnv {
  static isUse = false;
  static webmokEvn = null;
  static getCommonEnv() {
    if (CommonEnv.isUse) {
      return Promise.resolve(CommonEnv.webmokEvn);
    }
    return getEnv()
      .then((res) => {
        CommonEnv.isUse = true;
        CommonEnv.webmokEvn = res;
        return CommonEnv.webmokEvn;
      })
      .catch(() => {
        CommonEnv.isUse = true;
        return {
          surroundings: "",
          tripartite: "", //  微信小程序webView端; H5
        };
      });
    //
  }
}

export function getEnv() {
  return new Promise((resolve) => {
    const ua = navigator.userAgent.toLowerCase();   //获取判断用的对象
    const navigatorEnvironment = {
      surroundings: "",
      tripartite: "",
    };
    if (/MicroMessenger/gi.test(ua)) {
      navigatorEnvironment.tripartite = "weixin";
    }
    if (navigatorEnvironment.tripartite == "weixin") {
      if (/miniProgram/gi.test(ua)) {   //判断是微信小程序内嵌 or H5
        navigatorEnvironment.surroundings = "miniProgram";
      } 
      return resolve(navigatorEnvironment);
    } else {
      navigatorEnvironment.surroundings = "browser";
      return resolve(navigatorEnvironment);
    }
  });
}


2.提供channelRouter文件,根据宿主环境,提供页面跳转router,应用于CommonRouter

export const hasAgreementRegExp = /^(http|https):\/\/([\w.]+\/?)\S*/; //正则,绝对路径判断
export class BrowserRouter {
  constructor(router) {
    this.router = router;
  }
  go(url) {
    if (hasAgreementRegExp.test(url)) {
      return window.location.href = url;
    }
    this.router.push(url);
  }
  goBack() {
    this.router.goBack();
  }
  replace(url) {
    if (hasAgreementRegExp.test(url)) {
      return window.location.href = url;
    }
    this.router.replace(url);
  }
}

export class wxMinprogramRouter {
  constructor(router) {
    this.router = router;
  }
  go(originalUrl) {
    let url = handleWebviewUrl(originalUrl, hasAgreementRegExp.test(originalUrl));
    wx.miniProgram.navigateTo({ url });
  }
  goBack() {
    wx.miniProgram.navigateBack();
  }
  replace(originalUrl) {
    let url = handleWebviewUrl(originalUrl, hasAgreementRegExp.test(originalUrl));
    wx.miniProgram.redirectTo({ url });
  }
}

export function handleWebviewUrl(url, outLink = false) {
  const path = url.toString()[0] == "/" ? url : "/" + url;
  const webviewUrl = outLink ? url : `${window.location.origin}/${path}`;
  const miniProgramWebviewPath = "/pages/h5payment/webview/webview?weburl=";
  const navigateUrl = miniProgramWebviewPath + encodeURIComponent(webviewUrl);
  return navigateUrl;
}


3. 集成CommonRouter,

import { CommonEnv } from './commonEnv'
import { BrowserRouter, wxMinprogramRouter } from "./channelRouter";

export default class CommonRouter {
  static isUse = false;
  static params = null;
  static create({ ...params }) {
    CommonRouter.params = params;  //react-router提供的history对象
    if (CommonRouter.isUse) {
      return Promise.resolve(CommonRouter.CommonRouter);
    }
    return CommonEnv.getCommonEnv().then(({ surroundings, tripartite }) => {
      if (surroundings === "miniProgram" && tripartite === "weixin") {
        CommonRouter.CommonRouter = new wxMinprogramRouter();
        CommonRouter.isUse = true;
        return CommonRouter.CommonRouter;
      }
      CommonRouter.CommonRouter = new BrowserRouter(params);
      CommonRouter.isUse = true;
      return CommonRouter.CommonRouter;
    });
  }
  static go(url, outLink) {
    if (!url) return;
    if (CommonRouter.isUse) {
      CommonRouter.CommonRouter.go(url, outLink);
    } else {
      CommonRouter.create(CommonRouter.params).then((res) => {
        res.go(url, outLink);
      });
    }
  }
  static goBack() {
    if (CommonRouter.isUse) {
      CommonRouter.CommonRouter.goBack();
    } else {
      CommonRouter.create(CommonRouter.params).then((res) => {
        res.goBack();
      });
    }
  }
  static replace(url, outLink) {
    if (!url) return;
    if (CommonRouter.isUse) {
      CommonRouter.CommonRouter.replace(url, outLink);
    } else {
      CommonRouter.create(CommonRouter.params).then((res) => {
        res.replace(url, outLink);
      });
    }
  }
}

三.使用

  1. 根据自己的项目,在项目的入口文件初始化CommonRouter,简单举例如下:
import React from 'react';
import ReactDOM from 'react-dom';
import { withRouter } from "react-router-dom";
import CommonRouter from "app/route/commonRouter";

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);

class App extends React.Component {
  componentWillMount() {
    CommonRouter.create(this.props.history);
  }
  render() {
    return null
  }
}
export default withRouter(App);
回到顶部