|
@@ -1,11 +1,24 @@
|
|
|
import { PAGES, TABS } from "../ctx";
|
|
import { PAGES, TABS } from "../ctx";
|
|
|
import type { BackOptions, PageInstance, PushOptions } from "../types";
|
|
import type { BackOptions, PageInstance, PushOptions } from "../types";
|
|
|
-import { storage, last, isNull, isEmpty, get, isFunction, toArray, map, debounce } from "../utils";
|
|
|
|
|
|
|
+import {
|
|
|
|
|
+ storage,
|
|
|
|
|
+ last,
|
|
|
|
|
+ isNull,
|
|
|
|
|
+ isEmpty,
|
|
|
|
|
+ get,
|
|
|
|
|
+ isFunction,
|
|
|
|
|
+ toArray,
|
|
|
|
|
+ map,
|
|
|
|
|
+ debounce,
|
|
|
|
|
+ nth
|
|
|
|
|
+} from "../utils";
|
|
|
|
|
|
|
|
// 路由信息类型
|
|
// 路由信息类型
|
|
|
type RouteInfo = {
|
|
type RouteInfo = {
|
|
|
path: string;
|
|
path: string;
|
|
|
- meta?: UTSJSONObject;
|
|
|
|
|
|
|
+ query: UTSJSONObject;
|
|
|
|
|
+ meta: UTSJSONObject;
|
|
|
|
|
+ isAuth?: boolean;
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
// 跳转前钩子类型
|
|
// 跳转前钩子类型
|
|
@@ -21,15 +34,11 @@ type Events = {
|
|
|
|
|
|
|
|
// 路由核心类
|
|
// 路由核心类
|
|
|
export class Router {
|
|
export class Router {
|
|
|
- private _events = {} as Events; // 事件存储
|
|
|
|
|
|
|
+ private eventsMap = {} as Events; // 事件存储
|
|
|
|
|
|
|
|
// 获取缓存的路由参数
|
|
// 获取缓存的路由参数
|
|
|
params() {
|
|
params() {
|
|
|
- const data = storage.get("router-params") as UTSJSONObject;
|
|
|
|
|
- if (isNull(data)) {
|
|
|
|
|
- return {} as UTSJSONObject;
|
|
|
|
|
- }
|
|
|
|
|
- return data;
|
|
|
|
|
|
|
+ return (storage.get("router-params") ?? {}) as UTSJSONObject;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 获取默认路径,支持 home 和 login
|
|
// 获取默认路径,支持 home 和 login
|
|
@@ -38,6 +47,7 @@ export class Router {
|
|
|
home: PAGES[0].path, // 首页为第一个页面
|
|
home: PAGES[0].path, // 首页为第一个页面
|
|
|
login: "/pages/user/login"
|
|
login: "/pages/user/login"
|
|
|
};
|
|
};
|
|
|
|
|
+
|
|
|
return get(paths, name) as string;
|
|
return get(paths, name) as string;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -45,31 +55,38 @@ export class Router {
|
|
|
getPages(): PageInstance[] {
|
|
getPages(): PageInstance[] {
|
|
|
return map(getCurrentPages(), (e) => {
|
|
return map(getCurrentPages(), (e) => {
|
|
|
let path = e.route!;
|
|
let path = e.route!;
|
|
|
|
|
+
|
|
|
// 根路径自动转为首页
|
|
// 根路径自动转为首页
|
|
|
if (path == "/") {
|
|
if (path == "/") {
|
|
|
path = this.defaultPath("home");
|
|
path = this.defaultPath("home");
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
// 补全路径前缀
|
|
// 补全路径前缀
|
|
|
if (!path.startsWith("/")) {
|
|
if (!path.startsWith("/")) {
|
|
|
path = "/" + path;
|
|
path = "/" + path;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
// 获取页面样式
|
|
// 获取页面样式
|
|
|
const page = PAGES.find((e) => e.path == path);
|
|
const page = PAGES.find((e) => e.path == path);
|
|
|
const style = page?.style;
|
|
const style = page?.style;
|
|
|
const meta = page?.meta;
|
|
const meta = page?.meta;
|
|
|
|
|
+
|
|
|
// 获取页面暴露的方法
|
|
// 获取页面暴露的方法
|
|
|
// @ts-ignore
|
|
// @ts-ignore
|
|
|
- let exposed = e.vm as any;
|
|
|
|
|
|
|
+ const vm = e.vm as any;
|
|
|
|
|
+
|
|
|
|
|
+ let exposed = vm;
|
|
|
|
|
+
|
|
|
// #ifdef H5
|
|
// #ifdef H5
|
|
|
exposed = get(e, "vm.$.exposed");
|
|
exposed = get(e, "vm.$.exposed");
|
|
|
// #endif
|
|
// #endif
|
|
|
|
|
+
|
|
|
// 获取页面 query 参数
|
|
// 获取页面 query 参数
|
|
|
const query = (get(e, "options") ?? {}) as UTSJSONObject;
|
|
const query = (get(e, "options") ?? {}) as UTSJSONObject;
|
|
|
|
|
+
|
|
|
return {
|
|
return {
|
|
|
path,
|
|
path,
|
|
|
- // @ts-ignore
|
|
|
|
|
- vm: e.vm!,
|
|
|
|
|
- // @ts-ignore
|
|
|
|
|
|
|
+ vm,
|
|
|
exposed,
|
|
exposed,
|
|
|
style,
|
|
style,
|
|
|
meta,
|
|
meta,
|
|
@@ -113,7 +130,8 @@ export class Router {
|
|
|
complete,
|
|
complete,
|
|
|
animationType,
|
|
animationType,
|
|
|
animationDuration,
|
|
animationDuration,
|
|
|
- events
|
|
|
|
|
|
|
+ events,
|
|
|
|
|
+ isAuth
|
|
|
} = options;
|
|
} = options;
|
|
|
|
|
|
|
|
// 拼接 query 参数到 url
|
|
// 拼接 query 参数到 url
|
|
@@ -176,15 +194,15 @@ export class Router {
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
// 跳转前钩子处理
|
|
// 跳转前钩子处理
|
|
|
- if (isFunction(this._events["beforeEach"])) {
|
|
|
|
|
- const meta = PAGES.find((e) => e.path == path)?.meta;
|
|
|
|
|
- const from = this.getPages().slice(-1)[0];
|
|
|
|
|
- const to: RouteInfo = { path, meta: meta ?? {} };
|
|
|
|
|
- (this._events["beforeEach"] as BeforeEach)(
|
|
|
|
|
- to,
|
|
|
|
|
- from,
|
|
|
|
|
- next
|
|
|
|
|
- );
|
|
|
|
|
|
|
+ if (this.eventsMap.beforeEach != null) {
|
|
|
|
|
+ // 当前页
|
|
|
|
|
+ const from = last(this.getPages());
|
|
|
|
|
+
|
|
|
|
|
+ // 跳转页
|
|
|
|
|
+ const to = { path, meta: this.getMeta(path), query, isAuth } as RouteInfo;
|
|
|
|
|
+
|
|
|
|
|
+ // 调用跳转前钩子
|
|
|
|
|
+ this.eventsMap.beforeEach(to, from!, next);
|
|
|
} else {
|
|
} else {
|
|
|
next();
|
|
next();
|
|
|
}
|
|
}
|
|
@@ -197,31 +215,49 @@ export class Router {
|
|
|
});
|
|
});
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // 返回上一页,若为首页则回首页
|
|
|
|
|
|
|
+ // 返回上一页
|
|
|
back(options: BackOptions | null = null) {
|
|
back(options: BackOptions | null = null) {
|
|
|
- let path = ''
|
|
|
|
|
- const next = ()=>{
|
|
|
|
|
- if (this.isFirstPage()) {
|
|
|
|
|
- this.home();
|
|
|
|
|
- path = this.defaultPath("home")
|
|
|
|
|
- } else {
|
|
|
|
|
- path = this.getPages().slice(-2)[0].path;
|
|
|
|
|
|
|
+ if (this.isFirstPage()) {
|
|
|
|
|
+ this.home();
|
|
|
|
|
+ } else {
|
|
|
|
|
+ const delta = options?.delta ?? 1;
|
|
|
|
|
+
|
|
|
|
|
+ // 执行跳转函数
|
|
|
|
|
+ const next = () => {
|
|
|
uni.navigateBack({ ...(options ?? {}) });
|
|
uni.navigateBack({ ...(options ?? {}) });
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ // 跳转前钩子处理
|
|
|
|
|
+ if (this.eventsMap.beforeEach != null) {
|
|
|
|
|
+ // 当前页
|
|
|
|
|
+ const from = last(this.getPages());
|
|
|
|
|
+
|
|
|
|
|
+ // 上一页
|
|
|
|
|
+ const to = nth(this.getPages(), -delta - 1);
|
|
|
|
|
+
|
|
|
|
|
+ if (to != null) {
|
|
|
|
|
+ // 调用跳转前钩子
|
|
|
|
|
+ this.eventsMap.beforeEach(
|
|
|
|
|
+ {
|
|
|
|
|
+ path: to.path,
|
|
|
|
|
+ query: to.query,
|
|
|
|
|
+ meta: to.meta ?? ({} as UTSJSONObject)
|
|
|
|
|
+ },
|
|
|
|
|
+ from!,
|
|
|
|
|
+ next
|
|
|
|
|
+ );
|
|
|
|
|
+ } else {
|
|
|
|
|
+ console.error("[router] found to page is null");
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ next();
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
- // 跳转前钩子处理
|
|
|
|
|
- if (isFunction(this._events["beforeEach"])) {
|
|
|
|
|
- const meta = PAGES.find((e) => e.path == path)?.meta;
|
|
|
|
|
- const from = this.getPages().slice(-1)[0];
|
|
|
|
|
- const to: RouteInfo = { path, meta: meta ?? {} };
|
|
|
|
|
- (this._events["beforeEach"] as BeforeEach)(
|
|
|
|
|
- to,
|
|
|
|
|
- from,
|
|
|
|
|
- next
|
|
|
|
|
- );
|
|
|
|
|
- } else {
|
|
|
|
|
- next();
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 获取页面元数据
|
|
|
|
|
+ getMeta(path: string) {
|
|
|
|
|
+ return PAGES.find((e) => e.path.includes(path))?.meta ?? ({} as UTSJSONObject);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 执行当前页面暴露的方法
|
|
// 执行当前页面暴露的方法
|
|
@@ -296,21 +332,21 @@ export class Router {
|
|
|
});
|
|
});
|
|
|
}
|
|
}
|
|
|
// 登录后回调
|
|
// 登录后回调
|
|
|
- if (isFunction(this._events["afterLogin"])) {
|
|
|
|
|
- (this._events["afterLogin"] as AfterLogin)();
|
|
|
|
|
|
|
+ if (this.eventsMap.afterLogin != null) {
|
|
|
|
|
+ this.eventsMap.afterLogin!();
|
|
|
}
|
|
}
|
|
|
// 触发全局 afterLogin 事件
|
|
// 触发全局 afterLogin 事件
|
|
|
uni.$emit("afterLogin");
|
|
uni.$emit("afterLogin");
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 注册跳转前钩子
|
|
// 注册跳转前钩子
|
|
|
- beforeEach(callback: BeforeEach) {
|
|
|
|
|
- this._events["beforeEach"] = callback;
|
|
|
|
|
|
|
+ beforeEach(cb: BeforeEach) {
|
|
|
|
|
+ this.eventsMap.beforeEach = cb;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 注册登录后回调
|
|
// 注册登录后回调
|
|
|
- afterLogin(callback: AfterLogin) {
|
|
|
|
|
- this._events["afterLogin"] = callback;
|
|
|
|
|
|
|
+ afterLogin(cb: AfterLogin) {
|
|
|
|
|
+ this.eventsMap.afterLogin = cb;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|