初衷
在使用Taro或者是uniapp,开发的时候,跳转都需要写全路径,感觉非常的麻烦。
- 场景:想象一下,如果我们需要在跳转的时候需要判断要跳过去的页面是需要登录的。 如果我们不把路由跳转做第二次封装,可以想象的是,代码是非常混乱,且不好管理和维护
思路
- 使用一个对象装入整个项目的路由
- 把Taro路由跳转函数做二次封装
- 拿个中间件做路由的
options参数,判断和路由路径拼装 - 在跳转前,在写个函数来判断当前的状态是否是运行跳转到对应的页面(比如:有些页面是需要登录才能跳转的)
- 在所有条件都满足的情况下,进行跳转页面
代码实现
import { queryParams } from '../utils/utils'
import Taro from '@tarojs/taro'
import { RouterObj, RouterSkip } from '../type/router'
const router: RouterObj = Object.freeze({
'index': '/pages/index/index', //首页
'my': '/pages/my/index',//我的
})
const router_jurisdiction: string[] = ['my'] //那些页面需要登录权限
// 暴露路由接口
export class Router {
/**
* 取出路由地址
* @param key 路由对应的key
* @returns string
*/
static getRouter(key: string): string {
return router[key];
}
/**
* 拼接路由和参数
* @param url 路由对应的key
* @param data 页面之间要传的参数
* @returns
*/
static urlRoute<T>(url: string, data?: T): string {
// 获取要跳转的地址
url = router[url];
if (!url) return "";
let str = queryParams((data as any)); //把对象转换成路由后面的参数
return url + str; //返回路由和参数
}
// 跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面
static switchTab(options: RouterSkip): void {
jointRouter(options, 'switchTab')
}
// 关闭所有页面,打开到应用内的某个页面
static reLaunch(options: RouterSkip): void {
jointRouter(options, 'reLaunch')
}
// 关闭当前页面,跳转到应用内的某个页面。但是不允许跳转到 tabbar 页面
static redirectTo(options: RouterSkip): void {
jointRouter(options, 'redirectTo')
}
// 保留当前页面,跳转到应用内的某个页面。但是不能跳到 tabbar 页面。使用 Taro.navigateBack 可以返回到原页面。小程序中页面栈最多十层。
static navigateTo(options: RouterSkip): void {
jointRouter(options, 'navigateTo')
}
// 关闭当前页面,返回上一页面或多级页面。可通过 getCurrentPages 获取当前的页面栈,决定需要返回几层。
static navigateBack(options: RouterSkip): void {
jointRouter(options, 'navigateBack')
}
}
// 中间件,路由跳转前代理
function jointRouter(options: RouterSkip, type: string): boolean {
if (!options?.url) return false //判断当前是否传入路由地址
let key = options.url;//保存当前路由key
let url = Router.urlRoute<RouterObj>(options?.url, options?.data ?? {}); //从注册中获取路由
if (!url) return false //判断是否从注册中获取路由
options.url = url;
new TaroRouter(options, type, key) // 执行跳转处理
return true
}
// 路由跳转处理
class TaroRouter {
protected options: RouterSkip //对应的参数
protected type: string // 要跳转的类型
protected key: string // 路由的key 用于判断要跳转的路由是否需要登录
public constructor(options: RouterSkip, type: string, key: string) {
this.options = options;
this.type = type;
this.key = key;
this.intercept()
}
// 路由拦截
private intercept() {
// 判断是否登录过
let { key } = this;
if (router_jurisdiction.includes(key)) {
Taro.getBackgroundFetchToken({
success: (res) => {
console.log(res)
this.taroRouter()
},
fail: (err) => {
console.log(err);
// 如果要跳转的页面是需要登录的,但是当前状态是没有登录的
// TODO:: 当前没有登录需要做的处理
}
})
} else {
this.taroRouter()
}
}
// 路由跳转
private taroRouter() {
let { options, type } = this;
if (!Taro.hasOwnProperty(type)) return false;
Taro[type](options);
}
}
// 类型文件
import { Record } from '@tarojs/cli'
export interface RouterSkip {
url: string //需要跳转的应用内非 tabBar 的页面的路径, 路径后可以带参数。参数与路径之间使用 ? 分隔,参数键与参数值用 = 相连,不同参数用 & 分隔;如 'path?key=value&key2=value2'
data?: RouterObj //要传入下个页面的参数
complete?: Function//接口调用结束的回调函数(调用成功、失败都会执行)
fail?: Function //接口调用失败的回调函数
success?: Function //接口调用成功的回调函数
events?: Record//页面间通信接口,用于监听被打开页面发送到当前页面的数据
}