一.介绍
允许通过特定方式在H5页面集成小程序的路由,进行页面跳转,本篇文章H5已react react-router框架为例,大致流程如下:
首先需要提供一个判断H5当前运行环境的类(CommonEnv),对外只暴露CommonRouter类,CommonRouter类里面应集成各种应用渠道的路由跳转(如:浏览器,微信小程序),在H5页面的各个业务页面的路由跳转应只调用CommonRouter类上的方法
二.集成
- 创建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);
});
}
}
}
三.使用
- 根据自己的项目,在项目的入口文件初始化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);