易货app
This commit is contained in:
76
node_modules/uni-simple-router/src/H5/buildRouter.ts
generated
vendored
Normal file
76
node_modules/uni-simple-router/src/H5/buildRouter.ts
generated
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
import {RoutesRule, Router, routesMapRule, totalNextRoute, hookToggle, navtoRule} from '../options/base';
|
||||
import {H5Config} from '../options/config';
|
||||
import {warn} from '../helpers/warn'
|
||||
import {getDataType, getRoutePath} from '../helpers/utils'
|
||||
import { onTriggerEachHook } from '../public/hooks';
|
||||
|
||||
export function buildVueRoutes(router: Router, vueRouteMap:RoutesRule):RoutesRule {
|
||||
const {pathMap, finallyPathList} = (router.routesMap as routesMapRule);
|
||||
const vueRoutePathList:Array<string> = Object.keys(vueRouteMap);
|
||||
for (let i = 0; i < vueRoutePathList.length; i++) {
|
||||
const path = vueRoutePathList[i];
|
||||
const myRoute:RoutesRule = pathMap[path];
|
||||
const vueRoute:RoutesRule = vueRouteMap[path];
|
||||
if (!myRoute) {
|
||||
warn(`${path} 路由地址在路由表中未找到,确定是否传递漏啦`, router, true);
|
||||
} else {
|
||||
const {finallyPath} = getRoutePath(myRoute, router);
|
||||
if (finallyPath instanceof Array) {
|
||||
throw new Error(`非 vueRouterDev 模式下,alias、aliasPath、path 无法提供数组类型! ${JSON.stringify(myRoute)}`);
|
||||
}
|
||||
if (myRoute.name != null) {
|
||||
vueRoute.name = myRoute.name;
|
||||
}
|
||||
const vuePath = vueRoute['path'];
|
||||
const vueAlias = vueRoute['alias'];
|
||||
delete vueRoute['alias'];
|
||||
vueRoute['path'] = (finallyPath as string);
|
||||
if (vuePath === '/' && vueAlias != null) {
|
||||
vueRoute['alias'] = vueAlias;
|
||||
vueRoute['path'] = vuePath;
|
||||
}
|
||||
const beforeEnter = myRoute.beforeEnter;
|
||||
if (beforeEnter) {
|
||||
vueRoute['beforeEnter'] = function(
|
||||
to:totalNextRoute,
|
||||
from: totalNextRoute,
|
||||
next:(rule?: navtoRule|false)=>void,
|
||||
):void{
|
||||
onTriggerEachHook(to, from, router, hookToggle['enterHooks'], next)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
if (finallyPathList.includes('*')) {
|
||||
vueRouteMap['*'] = pathMap['*']
|
||||
}
|
||||
return vueRouteMap
|
||||
}
|
||||
|
||||
export function buildVueRouter(router:Router, vueRouter:any, vueRouteMap:RoutesRule|RoutesRule[]) :void |never {
|
||||
let routes:RoutesRule[] = [];
|
||||
if (getDataType<RoutesRule|RoutesRule[]>(vueRouteMap) === '[object Array]') {
|
||||
routes = (vueRouteMap as RoutesRule[]);
|
||||
} else {
|
||||
routes = Object.values(vueRouteMap);
|
||||
}
|
||||
const {scrollBehavior, fallback} = router.options.h5 as H5Config;
|
||||
const oldScrollBehavior = vueRouter.options.scrollBehavior;
|
||||
vueRouter.options.scrollBehavior = function proxyScrollBehavior(
|
||||
to:totalNextRoute,
|
||||
from:totalNextRoute,
|
||||
savedPosition:any
|
||||
) {
|
||||
oldScrollBehavior && oldScrollBehavior(to, from, savedPosition);
|
||||
return (scrollBehavior as Function)(to, from, savedPosition)
|
||||
}
|
||||
vueRouter.fallback = fallback;
|
||||
// Detail see: https://github.com/vuejs/vue-router/issues/1234#issuecomment-357941465
|
||||
const newVueRouter:any = new vueRouter.constructor({
|
||||
...router.options.h5,
|
||||
base: vueRouter.options.base,
|
||||
mode: vueRouter.options.mode,
|
||||
routes
|
||||
});
|
||||
vueRouter.matcher = newVueRouter.matcher;
|
||||
}
|
||||
71
node_modules/uni-simple-router/src/H5/proxyHook.ts
generated
vendored
Normal file
71
node_modules/uni-simple-router/src/H5/proxyHook.ts
generated
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
import {Router, proxyHookName, totalNextRoute, navtoRule} from '../options/base';
|
||||
|
||||
export class MyArray extends Array {
|
||||
constructor(
|
||||
private router:Router,
|
||||
private vueEachArray:Array<Function>,
|
||||
private myEachHook:Function,
|
||||
private hookName:'beforeHooks'| 'afterHooks',
|
||||
) {
|
||||
super();
|
||||
Object.setPrototypeOf(this, MyArray.prototype)
|
||||
}
|
||||
push(v:any):any {
|
||||
this.vueEachArray.push(v);
|
||||
const index = this.length;
|
||||
this[this.length] = (to: totalNextRoute, from: totalNextRoute, next:(rule?: navtoRule|false)=>void) => {
|
||||
if (index > 0) {
|
||||
this.vueEachArray[index](to, from, () => {
|
||||
next && next()
|
||||
});
|
||||
} else {
|
||||
this.myEachHook(to, from, (nextTo?:navtoRule|false) => {
|
||||
// Fixe https://github.com/SilurianYang/uni-simple-router/issues/241 2021年3月6日22:15:27
|
||||
// 目前不调用uni-app的守卫函数,因为会丢失页面栈信息
|
||||
if (nextTo === false) {
|
||||
next(false);
|
||||
} else {
|
||||
this.vueEachArray[index](to, from, (uniNextTo?:navtoRule|false) => {
|
||||
next(nextTo);
|
||||
})
|
||||
}
|
||||
}, this.router, true);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export function proxyEachHook(router:Router, vueRouter:any):void {
|
||||
const hookList:Array<'beforeHooks'| 'afterHooks'> = ['beforeHooks', 'afterHooks'];
|
||||
for (let i = 0; i < hookList.length; i++) {
|
||||
const hookName = hookList[i];
|
||||
const myEachHook = router.lifeCycle[(hookName as proxyHookName)][0];
|
||||
if (myEachHook) {
|
||||
const vueEachArray:Array<Function> = vueRouter[hookName];
|
||||
vueRouter[hookName] = new MyArray(router, vueEachArray, myEachHook, hookName);
|
||||
}
|
||||
}
|
||||
}
|
||||
export function proxyH5Mount(router:Router):void {
|
||||
if (router.mount.length === 0) {
|
||||
if (router.options.h5?.vueRouterDev) {
|
||||
return
|
||||
}
|
||||
const uAgent = navigator.userAgent;
|
||||
const isIos = !!uAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/)
|
||||
if (isIos) {
|
||||
// 【Fixe】 https://github.com/SilurianYang/uni-simple-router/issues/109
|
||||
setTimeout(() => {
|
||||
const element = document.getElementsByTagName('uni-page');
|
||||
if (element.length > 0) {
|
||||
return false
|
||||
}
|
||||
window.location.reload();
|
||||
}, 0);
|
||||
}
|
||||
} else {
|
||||
const [{app}] = router.mount;
|
||||
app.$mount();
|
||||
router.mount = [];
|
||||
}
|
||||
}
|
||||
40
node_modules/uni-simple-router/src/app/appPatch.ts
generated
vendored
Normal file
40
node_modules/uni-simple-router/src/app/appPatch.ts
generated
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
import { Router } from '../options/base';
|
||||
import { AppConfig } from '../options/config';
|
||||
|
||||
let quitBefore:number|null = null;
|
||||
|
||||
export function registerLoddingPage(
|
||||
router:Router,
|
||||
):void{
|
||||
if (router.options.registerLoadingPage) {
|
||||
const { loadingPageHook, loadingPageStyle } = router.options.APP as AppConfig; // 获取app所有配置
|
||||
const view = new plus.nativeObj.View('router-loadding', {
|
||||
top: '0px',
|
||||
left: '0px',
|
||||
height: '100%',
|
||||
width: '100%',
|
||||
...(loadingPageStyle as Function)()
|
||||
});
|
||||
(loadingPageHook as Function)(view); // 触发等待页面生命周期
|
||||
}
|
||||
}
|
||||
|
||||
export function runtimeQuit(
|
||||
title:string|undefined = '再按一次退出应用'
|
||||
):void{
|
||||
const nowTime = +new Date();
|
||||
if (!quitBefore) {
|
||||
quitBefore = nowTime;
|
||||
uni.showToast({
|
||||
title,
|
||||
icon: 'none',
|
||||
position: 'bottom',
|
||||
duration: 1000
|
||||
});
|
||||
setTimeout(() => { quitBefore = null }, 1000);
|
||||
} else {
|
||||
if (nowTime - quitBefore < 1000) {
|
||||
plus.runtime.quit();
|
||||
}
|
||||
}
|
||||
}
|
||||
18
node_modules/uni-simple-router/src/applets/appletPatch.ts
generated
vendored
Normal file
18
node_modules/uni-simple-router/src/applets/appletPatch.ts
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
import { Router} from '../options/base';
|
||||
|
||||
export function getEnterPath(
|
||||
vueVim:any,
|
||||
router:Router,
|
||||
) :string {
|
||||
switch (router.options.platform) {
|
||||
case 'mp-alipay':
|
||||
case 'mp-weixin':
|
||||
case 'mp-toutiao':
|
||||
case 'mp-qq':
|
||||
return vueVim.$options.mpInstance.route;
|
||||
case 'mp-baidu':
|
||||
// 【Fixe】 https://github.com/SilurianYang/uni-simple-router/issues/251
|
||||
return vueVim.$options.mpInstance.is || vueVim.$options.mpInstance.pageinstance.route;
|
||||
}
|
||||
return vueVim.$options.mpInstance.route; // 这是暂时的 因为除了以上的小程序 其他没测试 先这样写
|
||||
}
|
||||
79
node_modules/uni-simple-router/src/component/link.vue
generated
vendored
Normal file
79
node_modules/uni-simple-router/src/component/link.vue
generated
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
<template>
|
||||
<view @click="gotoPage()"><slot></slot></view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
const navType = {
|
||||
push: 'push',
|
||||
replace: 'replace',
|
||||
replaceAll: 'replaceAll',
|
||||
pushTab: 'pushTab',
|
||||
back:'back'
|
||||
};
|
||||
export default {
|
||||
props: {
|
||||
to: {
|
||||
type: [String, Object],
|
||||
required: true
|
||||
},
|
||||
stopNavto: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
navType: {
|
||||
type: String,
|
||||
default: 'push',
|
||||
},
|
||||
level: {
|
||||
type: Number,
|
||||
default: 1,
|
||||
},
|
||||
append: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
formatNav(text) {
|
||||
if (text != null && text.constructor === String) {
|
||||
text = text.replace(/\'/g, '');
|
||||
text = text.replace(/(\w+)(?=:)/g, function (val) {
|
||||
return `"${val}"`;
|
||||
});
|
||||
text = text.replace(/:\s*([^,{}\s"]+)/g, function (val) {
|
||||
const arr = val.split(':');
|
||||
return `:"${arr[1].trim()}"`;
|
||||
});
|
||||
try {
|
||||
text = JSON.parse(text);
|
||||
} catch (e) {}
|
||||
}
|
||||
if (this.append) {
|
||||
let pathArr = this.$Route.path.split('/');
|
||||
pathArr.splice(pathArr.length - this.level, this.level);
|
||||
pathArr = pathArr.join('/');
|
||||
if (text.constructor === Object) {
|
||||
if (text.path) {
|
||||
text.path = pathArr + text.path;
|
||||
}
|
||||
} else {
|
||||
text = pathArr + text;
|
||||
}
|
||||
}
|
||||
return text;
|
||||
},
|
||||
gotoPage() {
|
||||
if (this.stopNavto) {
|
||||
return true;
|
||||
}
|
||||
const type = navType[this.navType];
|
||||
if (type == null) {
|
||||
return console.error(` "navType" unknown type \n\n value:${Object.values(navType).join('、')}`);
|
||||
}
|
||||
const navInfo = this.formatNav(this.to);
|
||||
|
||||
this.$Router[type](navInfo);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
6
node_modules/uni-simple-router/src/global.d.ts
generated
vendored
Normal file
6
node_modules/uni-simple-router/src/global.d.ts
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
declare var uni:any;
|
||||
declare var plus:any;
|
||||
declare var __uniConfig:any;
|
||||
declare var __uniRoutes:any;
|
||||
declare function getCurrentPages(isAll:boolean|undefined=false):any;
|
||||
declare function getApp(args?:{allowDefault: true}):any;
|
||||
102
node_modules/uni-simple-router/src/helpers/config.ts
generated
vendored
Normal file
102
node_modules/uni-simple-router/src/helpers/config.ts
generated
vendored
Normal file
@@ -0,0 +1,102 @@
|
||||
import {err} from './warn'
|
||||
import {appletsVueHookConfig, appVueHookConfig, pageVueHookConfig, InstantiateConfig, LifeCycleConfig} from '../options/config'
|
||||
import { copyData} from './utils';
|
||||
import { appVueSortHookRule, pageVueSortHookRule, notCallProxyHookRule, comVueSortHookRule } from '../options/base';
|
||||
|
||||
export const keyword = ['query'];
|
||||
export const mpPlatformReg = '(^mp-weixin$)|(^mp-baidu$)|(^mp-alipay$)|(^mp-toutiao$)|(^mp-qq$)|(^mp-360$)' // 小程序下不能直接导出正则 需要重新组装成正则 不然bug一推 诡异
|
||||
|
||||
export const baseConfig:InstantiateConfig = {
|
||||
h5: {
|
||||
paramsToQuery: false,
|
||||
vueRouterDev: false,
|
||||
vueNext: false,
|
||||
mode: 'hash',
|
||||
base: '/',
|
||||
linkActiveClass: 'router-link-active',
|
||||
linkExactActiveClass: 'router-link-exact-active',
|
||||
scrollBehavior: (to:any, from:any, savedPostion:Function) => ({ x: 0, y: 0 }),
|
||||
fallback: true
|
||||
},
|
||||
APP: {
|
||||
registerLoadingPage: true,
|
||||
loadingPageStyle: () => JSON.parse('{"backgroundColor":"#FFF"}'),
|
||||
loadingPageHook: (view:any) => { view.show(); },
|
||||
launchedHook: () => { plus.navigator.closeSplashscreen(); },
|
||||
animation: {}
|
||||
},
|
||||
applet: {
|
||||
animationDuration: 300
|
||||
},
|
||||
platform: 'h5',
|
||||
keepUniOriginNav: false,
|
||||
debugger: false,
|
||||
routerBeforeEach: (to, from, next) => { next() },
|
||||
routerAfterEach: (to, from) => {},
|
||||
routerErrorEach: (error, router) => { router.$lockStatus = false; err(error, router, true); },
|
||||
detectBeforeLock: (router, to, navType) => {},
|
||||
routes: [
|
||||
{
|
||||
path: '/choose-location'
|
||||
},
|
||||
{
|
||||
path: '/open-location'
|
||||
},
|
||||
{
|
||||
path: '/preview-image'
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
export const lifeCycle:LifeCycleConfig = {
|
||||
beforeHooks: [],
|
||||
afterHooks: [],
|
||||
routerBeforeHooks: [],
|
||||
routerAfterHooks: [],
|
||||
routerErrorHooks: []
|
||||
};
|
||||
|
||||
export const appProxyHook:{
|
||||
app:appVueHookConfig
|
||||
} = {
|
||||
app: {
|
||||
created: [],
|
||||
beforeMount: [],
|
||||
mounted: [],
|
||||
onLaunch: [],
|
||||
onShow: [],
|
||||
onHide: [],
|
||||
beforeDestroy: [],
|
||||
destroyed: []
|
||||
}
|
||||
}
|
||||
export const indexProxyHook:appletsVueHookConfig = {
|
||||
app: appProxyHook.app,
|
||||
page: (function(
|
||||
appHooks:appVueHookConfig
|
||||
) :pageVueHookConfig {
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const {onLaunch, ...otherHooks} = appHooks;
|
||||
return {
|
||||
...otherHooks,
|
||||
onLoad: [],
|
||||
onReady: [],
|
||||
onUnload: [],
|
||||
onResize: []
|
||||
};
|
||||
})(copyData<appVueHookConfig>(appProxyHook.app)),
|
||||
component: []
|
||||
}
|
||||
|
||||
export const proxyVueSortHookName:{
|
||||
app:Array<appVueSortHookRule>,
|
||||
page:Array<pageVueSortHookRule>,
|
||||
component:Array<comVueSortHookRule>
|
||||
} = {
|
||||
app: ['created', 'beforeMount', 'mounted', 'onLaunch', 'onShow', 'onHide', 'beforeDestroy', 'destroyed'],
|
||||
page: ['created', 'beforeMount', 'mounted', 'onLoad', 'onReady', 'onShow', 'onResize', 'onHide', 'beforeDestroy', 'destroyed', 'onUnload'],
|
||||
component: ['created', 'beforeMount', 'mounted', 'beforeDestroy', 'destroyed']
|
||||
}
|
||||
export const notCallProxyHook:Array<notCallProxyHookRule> = [
|
||||
'onHide', 'beforeDestroy', 'destroyed', 'destroyed', 'onUnload', 'onResize'
|
||||
];
|
||||
47
node_modules/uni-simple-router/src/helpers/createRouteMap.ts
generated
vendored
Normal file
47
node_modules/uni-simple-router/src/helpers/createRouteMap.ts
generated
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
import {RoutesRule, Router, routesMapRule} from '../options/base';
|
||||
import {H5Config} from '../options/config';
|
||||
import {warn} from './warn'
|
||||
import {getRoutePath} from './utils'
|
||||
|
||||
export function createRouteMap(
|
||||
router: Router,
|
||||
routes: RoutesRule[],
|
||||
): routesMapRule|never {
|
||||
const routesMap:routesMapRule = {
|
||||
finallyPathList: [],
|
||||
finallyPathMap: Object.create(null),
|
||||
aliasPathMap: Object.create(null),
|
||||
pathMap: Object.create(null),
|
||||
vueRouteMap: Object.create(null),
|
||||
nameMap: Object.create(null)
|
||||
}
|
||||
routes.forEach(route => {
|
||||
const { finallyPath, aliasPath, path} = getRoutePath(route, router);
|
||||
if (path == null) {
|
||||
throw new Error(`请提供一个完整的路由对象,包括以绝对路径开始的 ‘path’ 字符串 ${JSON.stringify(route)}`);
|
||||
}
|
||||
if (finallyPath instanceof Array) {
|
||||
if (!(router.options.h5 as H5Config).vueRouterDev && router.options.platform === 'h5') {
|
||||
throw new Error(`非 vueRouterDev 模式下,route.alias 目前无法提供数组类型! ${JSON.stringify(route)}`);
|
||||
}
|
||||
}
|
||||
const strFinallyPath = (finallyPath as string);
|
||||
const strAliasPath = (aliasPath as string);
|
||||
if (router.options.platform !== 'h5') {
|
||||
if (strFinallyPath.indexOf('/') !== 0 && path !== '*') {
|
||||
warn(`当前路由对象下,route:${JSON.stringify(route)} 是否缺少了前缀 ‘/’`, router, true);
|
||||
}
|
||||
}
|
||||
if (!routesMap.finallyPathMap[strFinallyPath]) {
|
||||
routesMap.finallyPathMap[strFinallyPath] = route;
|
||||
routesMap.aliasPathMap[strAliasPath] = route;
|
||||
routesMap.pathMap[path] = route;
|
||||
routesMap.finallyPathList.push(strFinallyPath);
|
||||
if (route.name != null) {
|
||||
routesMap.nameMap[route.name] = route;
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return routesMap;
|
||||
}
|
||||
36
node_modules/uni-simple-router/src/helpers/lifeCycle.ts
generated
vendored
Normal file
36
node_modules/uni-simple-router/src/helpers/lifeCycle.ts
generated
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
import { navtoRule, navErrorRule, Router, proxyHookName, guardHookRule, totalNextRoute, hookToggle} from '../options/base';
|
||||
import { LifeCycleConfig, InstantiateConfig} from '../options/config';
|
||||
import {onTriggerEachHook} from '../public/hooks'
|
||||
|
||||
export function registerHook(list:Array<Function>, fn:Function):void {
|
||||
list[0] = fn;
|
||||
}
|
||||
|
||||
export function registerRouterHooks<T extends LifeCycleConfig>(cycleHooks:T, options:InstantiateConfig):T {
|
||||
registerHook(cycleHooks.routerBeforeHooks, function(to:totalNextRoute, from: totalNextRoute, next:(rule?: navtoRule|false)=>void):void {
|
||||
(options.routerBeforeEach as Function)(to, from, next);
|
||||
})
|
||||
registerHook(cycleHooks.routerAfterHooks, function(to:totalNextRoute, from: totalNextRoute):void {
|
||||
(options.routerAfterEach as Function)(to, from);
|
||||
})
|
||||
registerHook(cycleHooks.routerErrorHooks, function(error:navErrorRule, router:Router):void {
|
||||
(options.routerErrorEach as Function)(error, router);
|
||||
})
|
||||
return cycleHooks;
|
||||
}
|
||||
|
||||
export function registerEachHooks(router:Router, hookType:proxyHookName, userGuard:guardHookRule) {
|
||||
registerHook(router.lifeCycle[hookType], function(
|
||||
to:totalNextRoute,
|
||||
from: totalNextRoute,
|
||||
next:(rule?: navtoRule|false)=>void,
|
||||
router:Router,
|
||||
auto:boolean,
|
||||
):void {
|
||||
if (auto) { // h5端 vue-router自动触发 非自己调用触发
|
||||
onTriggerEachHook(to, from, router, hookToggle[hookType], next)
|
||||
} else {
|
||||
userGuard(to, from, next)
|
||||
}
|
||||
})
|
||||
}
|
||||
97
node_modules/uni-simple-router/src/helpers/mixins.ts
generated
vendored
Normal file
97
node_modules/uni-simple-router/src/helpers/mixins.ts
generated
vendored
Normal file
@@ -0,0 +1,97 @@
|
||||
import { Router, routesMapRule, RoutesRule, pageTypeRule} from '../options/base';
|
||||
import {createRouteMap} from '../helpers/createRouteMap'
|
||||
import {buildVueRoutes, buildVueRouter} from '../H5/buildRouter'
|
||||
import {proxyEachHook} from '../H5/proxyHook'
|
||||
import {registerLoddingPage} from '../app/appPatch';
|
||||
import { proxyPageHook } from '../public/page';
|
||||
import { forceGuardEach } from '../public/methods';
|
||||
import { assertParentChild } from './utils';
|
||||
import { getEnterPath } from '../applets/appletPatch';
|
||||
import { mpPlatformReg } from './config';
|
||||
|
||||
let registerRouter:boolean = false;
|
||||
let onloadProxyOk:boolean = false;
|
||||
const appletProxy:{
|
||||
app:boolean;
|
||||
page:string;
|
||||
} = {
|
||||
app: false,
|
||||
page: ''
|
||||
}
|
||||
|
||||
export function getMixins(Vue:any, router: Router):{
|
||||
beforeCreate(this: any): void;
|
||||
} | {
|
||||
beforeCreate(): void;
|
||||
} | {
|
||||
onLaunch(): void;
|
||||
} {
|
||||
let platform = router.options.platform;
|
||||
if (new RegExp(mpPlatformReg, 'g').test(platform)) {
|
||||
platform = 'app-lets';
|
||||
}
|
||||
const toggleHooks = {
|
||||
h5: {
|
||||
beforeCreate(this: any): void {
|
||||
if (this.$options.router) {
|
||||
router.$route = this.$options.router; // 挂载vue-router到路由对象下
|
||||
let vueRouteMap:RoutesRule[]|RoutesRule = [];
|
||||
if (router.options.h5?.vueRouterDev) {
|
||||
vueRouteMap = router.options.routes;
|
||||
} else {
|
||||
vueRouteMap = createRouteMap(router, this.$options.router.options.routes).finallyPathMap;
|
||||
(router.routesMap as routesMapRule).vueRouteMap = vueRouteMap;
|
||||
buildVueRoutes(router, vueRouteMap);
|
||||
}
|
||||
buildVueRouter(router, this.$options.router, vueRouteMap);
|
||||
proxyEachHook(router, this.$options.router);
|
||||
}
|
||||
}
|
||||
},
|
||||
'app-plus': {
|
||||
beforeCreate(this: any): void {
|
||||
if (!registerRouter) {
|
||||
registerRouter = true;
|
||||
proxyPageHook(this, router, 'appProxyHook', 'app');
|
||||
registerLoddingPage(router);
|
||||
}
|
||||
}
|
||||
},
|
||||
'app-lets': {
|
||||
beforeCreate(this: any): void {
|
||||
const pageType:pageTypeRule = this.$options.mpType;
|
||||
if (pageType === 'component' && !onloadProxyOk) {
|
||||
const isProxy = assertParentChild(appletProxy['page'], this);
|
||||
if (isProxy) {
|
||||
proxyPageHook(this, router, 'appletsProxyHook', pageType)
|
||||
}
|
||||
} else if (pageType !== 'component') {
|
||||
if (!appletProxy[pageType]) { // 没有处理
|
||||
if (pageType === 'page') {
|
||||
appletProxy[pageType] = getEnterPath(this, router);
|
||||
router.enterPath = appletProxy[pageType]; // 我不确定在不同端是否都是同样的变现?可能有的为非绝对路径?
|
||||
} else {
|
||||
appletProxy[pageType] = true;
|
||||
}
|
||||
proxyPageHook(this, router, 'appletsProxyHook', pageType)
|
||||
}
|
||||
}
|
||||
},
|
||||
onLoad(this: any):void{
|
||||
if (!onloadProxyOk && assertParentChild(appletProxy['page'], this)) {
|
||||
onloadProxyOk = true;
|
||||
forceGuardEach(router);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
return toggleHooks[(platform as 'h5'|'app-plus'|'app-lets')];
|
||||
}
|
||||
export function initMixins(Vue: any, router: Router) {
|
||||
const routesMap = createRouteMap(router, router.options.routes);
|
||||
router.routesMap = routesMap; // 挂载自身路由表到路由对象下
|
||||
// Vue.util.defineReactive(router, '_Route', createRoute(router, 19970806))
|
||||
Vue.mixin({
|
||||
...getMixins(Vue, router)
|
||||
});
|
||||
}
|
||||
523
node_modules/uni-simple-router/src/helpers/utils.ts
generated
vendored
Normal file
523
node_modules/uni-simple-router/src/helpers/utils.ts
generated
vendored
Normal file
@@ -0,0 +1,523 @@
|
||||
import {appVueHookConfig, H5Config, pageVueHookConfig, InstantiateConfig, appletsVueHookConfig, baseAppHookConfig} from '../options/config';
|
||||
import {RoutesRule, routesMapRule, routesMapKeysRule, Router, totalNextRoute, objectAny, navErrorRule, hookObjectRule, notCallProxyHookRule, NAVTYPE, navRoute, pageTypeRule} from '../options/base';
|
||||
import {baseConfig, notCallProxyHook, proxyVueSortHookName, keyword} from '../helpers/config';
|
||||
import {ERRORHOOK} from '../public/hooks'
|
||||
import {warnLock} from '../helpers/warn'
|
||||
import { createRoute, navjump } from '../public/methods';
|
||||
const Regexp = require('path-to-regexp');
|
||||
|
||||
export function voidFun():void{}
|
||||
|
||||
export function def(
|
||||
defObject:objectAny,
|
||||
key:string,
|
||||
getValue:Function
|
||||
) {
|
||||
Object.defineProperty(defObject, key, {
|
||||
get() {
|
||||
return getValue();
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export function timeOut(time:number):Promise<void> {
|
||||
return new Promise(resolve => {
|
||||
setTimeout(() => {
|
||||
resolve();
|
||||
}, time)
|
||||
})
|
||||
}
|
||||
|
||||
export function mergeConfig<T extends InstantiateConfig>(baseConfig: T, userConfig: T): T {
|
||||
const config: {[key: string]: any} = Object.create(null);
|
||||
const baseConfigKeys: Array<string> = Object.keys(baseConfig).concat(['resolveQuery', 'parseQuery']);
|
||||
for (let i = 0; i < baseConfigKeys.length; i += 1) {
|
||||
const key = baseConfigKeys[i];
|
||||
if (userConfig[key] != null) {
|
||||
if (userConfig[key].constructor === Object) {
|
||||
config[key] = {
|
||||
...baseConfig[key],
|
||||
...userConfig[key]
|
||||
};
|
||||
} else if (key === 'routes') {
|
||||
config[key] = [
|
||||
...baseConfig[key],
|
||||
...userConfig[key]
|
||||
];
|
||||
} else {
|
||||
config[key] = userConfig[key];
|
||||
}
|
||||
} else {
|
||||
config[key] = baseConfig[key];
|
||||
}
|
||||
}
|
||||
return config as T;
|
||||
}
|
||||
|
||||
export function notDeepClearNull<T>(object:T):T {
|
||||
for (const key in object) {
|
||||
if (object[key] == null) {
|
||||
delete object[key];
|
||||
}
|
||||
}
|
||||
return object;
|
||||
}
|
||||
|
||||
export function getRoutePath(route: RoutesRule, router:Router): {
|
||||
finallyPath: string | string[];
|
||||
aliasPath: string;
|
||||
path: string;
|
||||
alias: string | string[] | undefined;
|
||||
} {
|
||||
let finallyPath = route.aliasPath || route.alias || route.path;
|
||||
if (router.options.platform !== 'h5') {
|
||||
finallyPath = route.path
|
||||
}
|
||||
return {
|
||||
finallyPath,
|
||||
aliasPath: route.aliasPath || route.path,
|
||||
path: route.path,
|
||||
alias: route.alias
|
||||
}
|
||||
}
|
||||
|
||||
export function assertNewOptions<T extends InstantiateConfig>(
|
||||
options: T
|
||||
): T | never {
|
||||
const {platform, routes} = options;
|
||||
if (platform == null) {
|
||||
throw new Error(`你在实例化路由时必须传递 'platform'`);
|
||||
}
|
||||
if (routes == null || routes.length === 0) {
|
||||
throw new Error(`你在实例化路由时必须传递 routes 为空,这是无意义的。`);
|
||||
}
|
||||
if (options.platform === 'h5') {
|
||||
if (options.h5?.vueRouterDev) {
|
||||
baseConfig.routes = [];
|
||||
}
|
||||
}
|
||||
const mergeOptions = mergeConfig<T>(baseConfig as T, options);
|
||||
return mergeOptions;
|
||||
}
|
||||
|
||||
export function getWildcardRule(
|
||||
router:Router,
|
||||
msg?:navErrorRule
|
||||
):RoutesRule|never {
|
||||
const routesMap = (router.routesMap as routesMapRule);
|
||||
const route = routesMap.finallyPathMap['*'];
|
||||
if (route) { // 有写通配符
|
||||
return route
|
||||
}
|
||||
if (msg) {
|
||||
ERRORHOOK[0](msg, router);
|
||||
}
|
||||
throw new Error(`当前路由表匹配规则已全部匹配完成,未找到满足的匹配规则。你可以使用 '*' 通配符捕捉最后的异常`);
|
||||
}
|
||||
|
||||
export function notRouteTo404(
|
||||
router:Router,
|
||||
toRoute:RoutesRule|{
|
||||
redirect:any;
|
||||
path:string
|
||||
},
|
||||
parseToRule:totalNextRoute,
|
||||
navType:NAVTYPE
|
||||
):RoutesRule|totalNextRoute|never {
|
||||
if (toRoute.path !== '*') { // 不是通配符 正常匹配成功
|
||||
return (toRoute as RoutesRule);
|
||||
}
|
||||
|
||||
const redirect = toRoute.redirect;
|
||||
|
||||
if (typeof redirect === 'undefined') {
|
||||
throw new Error(` * 通配符必须配合 redirect 使用。redirect: string | Location | Function`);
|
||||
}
|
||||
|
||||
let newRoute = redirect;
|
||||
if (typeof newRoute === 'function') {
|
||||
newRoute = newRoute(parseToRule) as totalNextRoute;
|
||||
}
|
||||
const redirectRule = navjump(newRoute as totalNextRoute, router, navType, undefined, undefined, undefined, false);
|
||||
return (redirectRule as totalNextRoute);
|
||||
}
|
||||
|
||||
export function routesForMapRoute(
|
||||
router: Router,
|
||||
path: string,
|
||||
mapArrayKey:Array<routesMapKeysRule>
|
||||
):RoutesRule|never {
|
||||
if (router.options.h5?.vueRouterDev) {
|
||||
return {path}
|
||||
}
|
||||
// 【Fixe】 https://github.com/SilurianYang/uni-simple-router/issues/252
|
||||
const startPath = path.split('?')[0];
|
||||
let wildcard = '';
|
||||
const routesMap = (router.routesMap as routesMapRule);
|
||||
for (let i = 0; i < mapArrayKey.length; i++) {
|
||||
const mapKey = mapArrayKey[i];
|
||||
const mapList = routesMap[mapKey];
|
||||
for (const [key, value] of Object.entries(mapList)) {
|
||||
if (key === '*') {
|
||||
if (wildcard === '') {
|
||||
wildcard = '*'
|
||||
}
|
||||
continue;
|
||||
}
|
||||
const route:string|RoutesRule = value;
|
||||
let rule:string = key;
|
||||
if (getDataType<Array<string>|objectAny>(mapList) === '[object Array]') {
|
||||
rule = (route as string);
|
||||
}
|
||||
const pathRule:RegExp = Regexp(rule);
|
||||
const result = pathRule.exec(startPath);
|
||||
if (result != null) {
|
||||
if (getDataType<string|RoutesRule>(route) === '[object String]') {
|
||||
return routesMap.finallyPathMap[(route as string)];
|
||||
}
|
||||
return (route as RoutesRule);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (wildcard !== '') {
|
||||
return getWildcardRule(router);
|
||||
}
|
||||
throw new Error(`${path} 路径无法在路由表中找到!检查跳转路径及路由表`);
|
||||
}
|
||||
|
||||
export function getDataType<T>(data:T):string {
|
||||
return Object.prototype.toString.call(data)
|
||||
}
|
||||
|
||||
export function copyData<T>(object:T): T {
|
||||
return JSON.parse(JSON.stringify(object))
|
||||
}
|
||||
|
||||
export function getUniCachePage<T extends objectAny>(pageIndex?:number):T|[] {
|
||||
const pages:T = getCurrentPages();
|
||||
if (pageIndex == null) {
|
||||
return pages
|
||||
}
|
||||
if (pages.length === 0) {
|
||||
return pages;
|
||||
}
|
||||
const page = pages.reverse()[pageIndex];
|
||||
if (page == null) {
|
||||
return []
|
||||
}
|
||||
return page;
|
||||
}
|
||||
|
||||
export function urlToJson(url :string):{
|
||||
path:string;
|
||||
query:objectAny
|
||||
} {
|
||||
const query:objectAny = {};
|
||||
const [path, params] = url.split('?');
|
||||
if (params != null) {
|
||||
const parr = params.split('&');
|
||||
for (const i of parr) {
|
||||
const arr = i.split('=');
|
||||
query[arr[0]] = arr[1];
|
||||
}
|
||||
}
|
||||
return {
|
||||
path,
|
||||
query
|
||||
}
|
||||
}
|
||||
|
||||
export function forMatNextToFrom<T extends totalNextRoute>(
|
||||
router:Router,
|
||||
to:T,
|
||||
from:T
|
||||
):{
|
||||
matTo:T;
|
||||
matFrom: T;
|
||||
} {
|
||||
let [matTo, matFrom] = [to, from];
|
||||
if (router.options.platform === 'h5') {
|
||||
const {vueNext, vueRouterDev} = (router.options.h5 as H5Config);
|
||||
if (!vueNext && !vueRouterDev) {
|
||||
matTo = createRoute(router, undefined, matTo) as T;
|
||||
matFrom = createRoute(router, undefined, matFrom) as T;
|
||||
}
|
||||
} else {
|
||||
matTo = createRoute(router, undefined, deepClone<T>(matTo)) as T;
|
||||
matFrom = createRoute(router, undefined, deepClone<T>(matFrom)) as T;
|
||||
}
|
||||
return {
|
||||
matTo: matTo,
|
||||
matFrom: matFrom
|
||||
}
|
||||
}
|
||||
|
||||
export function paramsToQuery(
|
||||
router:Router,
|
||||
toRule:totalNextRoute|string
|
||||
):totalNextRoute|string {
|
||||
if (router.options.platform === 'h5' && !router.options.h5?.paramsToQuery) {
|
||||
return toRule;
|
||||
}
|
||||
if (getDataType<totalNextRoute|string>(toRule) === '[object Object]') {
|
||||
const {name, params, ...moreToRule} = (toRule as totalNextRoute);
|
||||
let paramsQuery = params;
|
||||
if (router.options.platform !== 'h5' && paramsQuery == null) {
|
||||
paramsQuery = {};
|
||||
}
|
||||
if (name != null && paramsQuery != null) {
|
||||
let route = (router.routesMap as routesMapRule).nameMap[name];
|
||||
if (route == null) {
|
||||
route = getWildcardRule(router, { type: 2, msg: `命名路由为:${name} 的路由,无法在路由表中找到!`, toRule});
|
||||
}
|
||||
const {finallyPath} = getRoutePath(route, router);
|
||||
if (finallyPath.includes(':')) { // 动态路由无法使用 paramsToQuery
|
||||
ERRORHOOK[0]({ type: 2, msg: `动态路由:${finallyPath} 无法使用 paramsToQuery!`, toRule}, router);
|
||||
} else {
|
||||
return {
|
||||
...moreToRule,
|
||||
path: finallyPath as string,
|
||||
query: paramsQuery
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return toRule
|
||||
}
|
||||
|
||||
export function assertDeepObject(object:objectAny):boolean {
|
||||
let arrMark = null;
|
||||
try {
|
||||
arrMark = JSON.stringify(object).match(/\{|\[|\}|\]/g);
|
||||
} catch (error) {
|
||||
warnLock(`传递的参数解析对象失败。` + error)
|
||||
}
|
||||
if (arrMark == null) {
|
||||
return false
|
||||
}
|
||||
if (arrMark.length > 3) {
|
||||
return true;
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
export function baseClone<
|
||||
T extends {
|
||||
[key:string]:any
|
||||
}, K extends keyof T
|
||||
>(
|
||||
source:T,
|
||||
target:Array<any>|objectAny
|
||||
):void {
|
||||
for (const key of Object.keys(source)) {
|
||||
const dyKey = key as T[K];
|
||||
if (source[key] === source) continue
|
||||
if (typeof source[key] === 'object') {
|
||||
target[dyKey] = getDataType<T>(source[key]) === '[object Array]' ? ([] as Array<any>) : ({} as objectAny)
|
||||
baseClone(source[key], target[dyKey])
|
||||
} else {
|
||||
target[dyKey] = source[key]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function deepClone<T>(source:T):T {
|
||||
const __ob__ = getDataType<T>(source) === '[object Array]' ? ([] as Array<any>) : ({} as objectAny);
|
||||
baseClone(source, __ob__)
|
||||
return __ob__ as T
|
||||
}
|
||||
|
||||
export function lockDetectWarn(
|
||||
router:Router,
|
||||
to:string|number|totalNextRoute|navRoute,
|
||||
navType:NAVTYPE,
|
||||
next:Function,
|
||||
passiveType?:'beforeHooks'| 'afterHooks'
|
||||
):void{
|
||||
if (passiveType === 'afterHooks') {
|
||||
next();
|
||||
} else {
|
||||
const {detectBeforeLock} = router.options;
|
||||
detectBeforeLock && detectBeforeLock(router, to, navType);
|
||||
if (router.$lockStatus) {
|
||||
(router.options.routerErrorEach as (error: navErrorRule, router:Router) => void)({
|
||||
type: 2,
|
||||
msg: '当前页面正在处于跳转状态,请稍后再进行跳转....'
|
||||
}, router);
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function replaceHook(
|
||||
router:Router,
|
||||
vueVim:any,
|
||||
proxyHookKey:'appProxyHook'|'appletsProxyHook',
|
||||
pageType:pageTypeRule,
|
||||
):void{
|
||||
const vueOptions:appVueHookConfig|pageVueHookConfig = vueVim.$options;
|
||||
const proxyHook = router[proxyHookKey][(pageType as 'app')];
|
||||
let proxyHookChild:baseAppHookConfig|objectAny = {};
|
||||
if (getDataType(proxyHook) === '[object Array]') {
|
||||
proxyHookChild = {
|
||||
beforeCreate: [],
|
||||
created: [],
|
||||
beforeMount: [],
|
||||
mounted: [],
|
||||
beforeDestroy: [],
|
||||
destroyed: []
|
||||
}
|
||||
}
|
||||
if (proxyHook != null) {
|
||||
const proxyName = proxyVueSortHookName[pageType];
|
||||
for (let i = 0; i < proxyName.length; i++) {
|
||||
const keyName = proxyName[i];
|
||||
const originHook = vueOptions[keyName] as Array<Function>|undefined;
|
||||
if (getDataType<Array<Function>|undefined>(originHook) === '[object Array]') {
|
||||
const proxyInfo:hookObjectRule = {
|
||||
options: [],
|
||||
hook: Function
|
||||
};
|
||||
const hook = (originHook as Array<Function>).splice((originHook as Array<Function>).length - 1, 1, (...options:Array<any>) => (proxyInfo.options = options))[0]
|
||||
proxyInfo.hook = function resetHook(enterPath:string):Function {
|
||||
if (router.enterPath.replace(/^\//, '') !== enterPath.replace(/^\//, '') && pageType !== 'app') {
|
||||
return () => {};
|
||||
}
|
||||
if (!notCallProxyHook.includes(keyName as notCallProxyHookRule)) {
|
||||
hook.apply(vueVim, proxyInfo.options)
|
||||
}
|
||||
return () => {
|
||||
(originHook as Array<Function>).splice((originHook as Array<Function>).length - 1, 1, hook);
|
||||
};
|
||||
}
|
||||
if (Object.keys(proxyHookChild).length > 0) {
|
||||
proxyHookChild[(keyName as string)] = [proxyInfo];
|
||||
} else {
|
||||
proxyHook[keyName] = [proxyInfo]
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Object.keys(proxyHookChild).length > 0) {
|
||||
// @ts-ignore
|
||||
(proxyHook as appletsVueHookConfig['component']).push(proxyHookChild);
|
||||
}
|
||||
}
|
||||
}
|
||||
export function callHook(
|
||||
value:objectAny,
|
||||
enterPath:string
|
||||
):Array<Function> {
|
||||
const resetHookFun:Array<Function> = [];
|
||||
for (const [, [origin]] of Object.entries(value as objectAny)) {
|
||||
if (origin && origin.hook) {
|
||||
resetHookFun.push(origin.hook(enterPath))
|
||||
}
|
||||
}
|
||||
return resetHookFun;
|
||||
}
|
||||
export function resetPageHook(
|
||||
router:Router,
|
||||
enterPath:string
|
||||
):void{
|
||||
// Fixe: https://github.com/SilurianYang/uni-simple-router/issues/206
|
||||
const pathInfo = enterPath.trim().match(/^(\/?[^\?\s]+)(\?[\s\S]*$)?$/);
|
||||
if (pathInfo == null) {
|
||||
throw new Error(`还原hook失败。请检查 【${enterPath}】 路径是否正确。`);
|
||||
}
|
||||
enterPath = pathInfo[1];
|
||||
let proxyHookKey:'appProxyHook'|'appletsProxyHook' = 'appletsProxyHook';
|
||||
if (router.options.platform === 'app-plus') {
|
||||
proxyHookKey = 'appProxyHook';
|
||||
}
|
||||
let resetHookFun:Array<Function> = [];
|
||||
for (const [, value] of Object.entries(router[proxyHookKey])) {
|
||||
if (getDataType(value) === '[object Array]') {
|
||||
for (let i = 0; i < value.length; i++) {
|
||||
resetHookFun = resetHookFun.concat(callHook(value[i], enterPath));
|
||||
}
|
||||
} else {
|
||||
resetHookFun = resetHookFun.concat(callHook(value, enterPath));
|
||||
}
|
||||
}
|
||||
setTimeout(() => {
|
||||
for (let i = 0; i < resetHookFun.length; i++) {
|
||||
resetHookFun[i]();
|
||||
}
|
||||
}, 500)
|
||||
}
|
||||
|
||||
export function reservedWord(
|
||||
params:string|totalNextRoute
|
||||
):string|totalNextRoute {
|
||||
if (typeof params === 'string') {
|
||||
return params
|
||||
}
|
||||
|
||||
const query = {
|
||||
...(copyData(params.params || {}) as object),
|
||||
...(copyData(params.query || {}) as object)
|
||||
};
|
||||
for (let i = 0; i < keyword.length; i++) {
|
||||
const hasKey = keyword[i];
|
||||
if (Reflect.has(query, hasKey)) {
|
||||
if (getDataType(params.query) === '[object Object]') {
|
||||
delete (params.query as objectAny)[hasKey];
|
||||
}
|
||||
if (getDataType(params.params) === '[object Object]') {
|
||||
delete (params.params as objectAny)[hasKey];
|
||||
}
|
||||
warnLock(`${JSON.stringify(keyword)} 作为插件的保留字,在参数传递中不允许使用。已自动被过滤掉!换个参数名试试吧! `)
|
||||
}
|
||||
}
|
||||
|
||||
return params
|
||||
}
|
||||
|
||||
export function assertParentChild(
|
||||
parentPath:string,
|
||||
vueVim:any,
|
||||
):boolean {
|
||||
while (vueVim.$parent != null) {
|
||||
const mpPage = vueVim.$parent.$mp;
|
||||
if (mpPage.page && mpPage.page.is === parentPath) {
|
||||
return true;
|
||||
}
|
||||
vueVim = vueVim.$parent;
|
||||
}
|
||||
try {
|
||||
if (vueVim.$mp.page.is === parentPath || vueVim.$mp.page.route === parentPath) {
|
||||
return true
|
||||
}
|
||||
} catch (error) {
|
||||
return false
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
export function resolveAbsolutePath(
|
||||
path:string,
|
||||
router:Router
|
||||
):string|never {
|
||||
const reg = /^\/?([^\?\s]+)(\?.+)?$/;
|
||||
const trimPath = path.trim();
|
||||
if (!reg.test(trimPath)) {
|
||||
throw new Error(`【${path}】 路径错误,请提供完整的路径(10001)。`);
|
||||
}
|
||||
const paramsArray = trimPath.match(reg);
|
||||
if (paramsArray == null) {
|
||||
throw new Error(`【${path}】 路径错误,请提供完整的路径(10002)。`);
|
||||
}
|
||||
const query:string = paramsArray[2] || '';
|
||||
if (/^\.\/[^\.]+/.test(trimPath)) { // 当前路径下
|
||||
const navPath:string = router.currentRoute.path + path;
|
||||
return navPath.replace(/[^\/]+\.\//, '');
|
||||
}
|
||||
const relative = paramsArray[1].replace(/\//g, `\\/`).replace(/\.\./g, `[^\\/]+`).replace(/\./g, '\\.');
|
||||
const relativeReg = new RegExp(`^\\/${relative}$`);
|
||||
const route = router.options.routes.filter(it => relativeReg.test(it.path));
|
||||
if (route.length !== 1) {
|
||||
throw new Error(`【${path}】 路径错误,尝试转成绝对路径失败,请手动转成绝对路径(10003)。`);
|
||||
}
|
||||
return route[0].path + query;
|
||||
}
|
||||
37
node_modules/uni-simple-router/src/helpers/warn.ts
generated
vendored
Normal file
37
node_modules/uni-simple-router/src/helpers/warn.ts
generated
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
|
||||
import {debuggerConfig, debuggerArrayConfig} from '../options/config'
|
||||
import {Router} from '../options/base'
|
||||
|
||||
type callType='error'|'warn'|'log';
|
||||
|
||||
export function isLog(type:callType, dev:debuggerConfig, errText:any, enforce:boolean = false):boolean {
|
||||
if (!enforce) {
|
||||
const isObject = dev.toString() === '[object Object]';
|
||||
if (dev === false) {
|
||||
return false
|
||||
} else if (isObject) {
|
||||
if ((dev as debuggerArrayConfig)[type] === false) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
console[type](errText);
|
||||
return true;
|
||||
}
|
||||
export function err(errText:any, router:Router, enforce?:boolean):void {
|
||||
const dev = (router.options.debugger as debuggerConfig);
|
||||
isLog('error', dev, errText, enforce);
|
||||
}
|
||||
|
||||
export function warn(errText:any, router:Router, enforce?:boolean):void {
|
||||
const dev = (router.options.debugger as debuggerConfig);
|
||||
isLog('warn', dev, errText, enforce);
|
||||
}
|
||||
|
||||
export function log(errText:any, router:Router, enforce?:boolean):void {
|
||||
const dev = (router.options.debugger as debuggerConfig);
|
||||
isLog('log', dev, errText, enforce);
|
||||
}
|
||||
export function warnLock(errText:any):void {
|
||||
console.warn(errText);
|
||||
}
|
||||
11
node_modules/uni-simple-router/src/index.ts
generated
vendored
Normal file
11
node_modules/uni-simple-router/src/index.ts
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
export * from './options/base'
|
||||
export * from './options/config'
|
||||
|
||||
export {
|
||||
runtimeQuit
|
||||
} from './app/appPatch'
|
||||
|
||||
export {
|
||||
RouterMount,
|
||||
createRouter
|
||||
} from './public/router'
|
||||
236
node_modules/uni-simple-router/src/options/base.ts
generated
vendored
Normal file
236
node_modules/uni-simple-router/src/options/base.ts
generated
vendored
Normal file
@@ -0,0 +1,236 @@
|
||||
import {appletsVueHookConfig, appVueHookConfig, InstantiateConfig, LifeCycleConfig} from '../options/config';
|
||||
|
||||
export enum hookToggle{
|
||||
'beforeHooks'='beforeEach',
|
||||
'afterHooks'='afterEach',
|
||||
'enterHooks'='beforeEnter'
|
||||
}
|
||||
export enum navtypeToggle{
|
||||
'push'='navigateTo',
|
||||
'replace'='redirectTo',
|
||||
'replaceAll'='reLaunch',
|
||||
'pushTab'='switchTab',
|
||||
'back'='navigateBack'
|
||||
}
|
||||
export enum rewriteMethodToggle{
|
||||
'navigateTo'='push',
|
||||
'navigate'='push',
|
||||
'redirectTo'='replace',
|
||||
'reLaunch'='replaceAll',
|
||||
'switchTab'='pushTab',
|
||||
'navigateBack'='back',
|
||||
}
|
||||
export type backTypeRule='backbutton'|'navigateBack'
|
||||
export type pageTypeRule='app'|'page'|'component';
|
||||
export type notCallProxyHookRule='onHide'|'beforeDestroy'|'destroyed'|'onUnload'|'onResize';
|
||||
export type appVueSortHookRule='beforeCreate'|'created'|'beforeMount'|'mounted'|'onLaunch'|'onShow'|'onHide'|'beforeDestroy'|'destroyed';
|
||||
export type pageVueSortHookRule='beforeCreate'|'created'|'beforeMount'|'mounted'|'onLoad'|'onReady'|'onShow'|'onResize'|'onHide'|'beforeDestroy'|'destroyed'|'onUnload';
|
||||
export type comVueSortHookRule= 'beforeCreate'|'created'| 'beforeMount'| 'mounted'|'beforeDestroy'| 'destroyed';
|
||||
export type reNavMethodRule='navigateTo'|'redirectTo'|'reLaunch'|'switchTab';
|
||||
export type reNotNavMethodRule='navigateBack';
|
||||
export type reloadNavRule=totalNextRoute | false | undefined|string;
|
||||
export type hookListRule=Array<(router:Router, to:totalNextRoute, from: totalNextRoute, toRoute:RoutesRule,next:Function)=>void>
|
||||
export type guardHookRule=(to: totalNextRoute, from: totalNextRoute, next:(rule?: navtoRule|false)=>void)=>void;
|
||||
export type navRuleStatus= 0|1|2|3; //0: next(false) 1:next(unknownType) 2:加锁状态,禁止跳转 3:在获取页面栈的时候,页面栈不够level获取
|
||||
export type proxyHookName='beforeHooks'|'afterHooks';
|
||||
export type navMethodRule = Promise<void | undefined | navRuleStatus>;
|
||||
export type objectAny={[propName: string]: any;};
|
||||
export type NAVTYPE = 'push' | 'replace' | 'replaceAll' | 'pushTab'|'back';
|
||||
export type startAnimationType =
|
||||
| 'slide-in-right'
|
||||
| 'slide-in-left'
|
||||
| 'slide-in-top'
|
||||
| 'slide-in-bottom'
|
||||
| 'pop-in'
|
||||
| 'fade-in'
|
||||
| 'zoom-out'
|
||||
| 'zoom-fade-out'
|
||||
| 'none';
|
||||
export type endAnimationType =
|
||||
| 'slide-out-right'
|
||||
| 'slide-out-left'
|
||||
| 'slide-out-top'
|
||||
| 'slide-out-bottom'
|
||||
| 'pop-out'
|
||||
| 'fade-out'
|
||||
| 'zoom-in'
|
||||
| 'zoom-fade-in'
|
||||
| 'none';
|
||||
|
||||
// 跳转api时,传递的跳转规则
|
||||
export interface navtoRule {
|
||||
NAVTYPE?: NAVTYPE; // 跳转类型 v1.1.0+
|
||||
path?: string; // 跳转路径 绝对路径
|
||||
name?: string | undefined; // 跳转路径名称
|
||||
query?: objectAny; // 跳转使用path时 query包含需要传递的参数
|
||||
params?: objectAny; // 跳转使用name时 params包含需要传递的参数
|
||||
animationType?: startAnimationType|endAnimationType;
|
||||
animationDuration?: number;
|
||||
events?: objectAny;
|
||||
success?: Function;
|
||||
fail?: Function;
|
||||
complete?: Function;
|
||||
}
|
||||
// h5 next管道函数中传递的from及to对象
|
||||
export interface h5NextRule {
|
||||
fullPath?: string | undefined;
|
||||
hash?: string | undefined;
|
||||
matched?: Array<object>;
|
||||
meta?: object;
|
||||
name?: undefined | string;
|
||||
type?: undefined | string;
|
||||
}
|
||||
|
||||
export interface totalNextRoute extends h5NextRule, navtoRule {
|
||||
path:string;
|
||||
delta?:number;
|
||||
[propName: string]: any;
|
||||
}
|
||||
export interface navRoute extends h5NextRule, navtoRule {
|
||||
|
||||
}
|
||||
|
||||
// 开始切换窗口动画 app端可用
|
||||
export interface startAnimationRule {
|
||||
animationType?: startAnimationType; // 窗口关闭的动画效果
|
||||
animationDuration?: number; // 窗口关闭动画的持续时间
|
||||
}
|
||||
// 关闭窗口时的动画 app端可用
|
||||
export interface endAnimationRule {
|
||||
animationType?: endAnimationType; // 窗口关闭的动画效果
|
||||
animationDuration?: number; // 窗口关闭动画的持续时间
|
||||
}
|
||||
export interface hookObjectRule {
|
||||
options:Array<any>;
|
||||
hook:Function;
|
||||
}
|
||||
|
||||
// 执行路由跳转失败或者 next(false) 时走的规则
|
||||
export interface navErrorRule {
|
||||
type: navRuleStatus;
|
||||
msg: string;
|
||||
to?:totalNextRoute;
|
||||
from?:totalNextRoute;
|
||||
nextTo?:any;
|
||||
[propName:string]:any;
|
||||
}
|
||||
// uni原生api跳转时的规则
|
||||
export interface uniNavApiRule {
|
||||
url: string;
|
||||
openType?:'appLaunch',
|
||||
query?:objectAny;
|
||||
path?:string;
|
||||
delta?:number;
|
||||
detail?:{[propName:string]:any};
|
||||
animationType?:startAnimationType;
|
||||
animationDuration?:number;
|
||||
events?:{[propName:string]:any};
|
||||
success?:Function;
|
||||
fail?:Function;
|
||||
complete?:Function;
|
||||
animation?:{
|
||||
animationType?:startAnimationType;
|
||||
animationDuration?:number;
|
||||
}
|
||||
}
|
||||
|
||||
export interface originMixins extends uniNavApiRule{
|
||||
BACKTYPE:''|backTypeRule
|
||||
}
|
||||
|
||||
// uni-app 原始返回api 回调参数
|
||||
export interface uniBackRule{
|
||||
from:backTypeRule;
|
||||
}
|
||||
|
||||
export interface uniBackApiRule{
|
||||
delta?: number;
|
||||
animationDuration?: number;
|
||||
animationType?:endAnimationType;
|
||||
}
|
||||
|
||||
export type routesMapKeysRule=
|
||||
'finallyPathList'|
|
||||
'finallyPathMap'|
|
||||
'aliasPathMap'|
|
||||
'pathMap'|
|
||||
'nameMap'|
|
||||
'vueRouteMap';
|
||||
|
||||
export interface routesMapRule{
|
||||
[key:string]:any;
|
||||
finallyPathList: Array<string>;
|
||||
finallyPathMap:RoutesRule;
|
||||
aliasPathMap: RoutesRule;
|
||||
pathMap: RoutesRule;
|
||||
nameMap:RoutesRule,
|
||||
vueRouteMap:objectAny
|
||||
}
|
||||
|
||||
export interface routeRule{
|
||||
name:string|undefined;
|
||||
meta:objectAny;
|
||||
path:string;
|
||||
query:objectAny;
|
||||
params:objectAny;
|
||||
fullPath:string;
|
||||
NAVTYPE:NAVTYPE|'';
|
||||
BACKTYPE?:backTypeRule|''; // v2.0.5 +
|
||||
[propName: string]: any;
|
||||
}
|
||||
|
||||
|
||||
export interface RoutesRule {
|
||||
path: string; // pages.json中的path 必须加上 '/' 开头
|
||||
component?: object; // H5端可用
|
||||
name?: string; // 命名路由
|
||||
components?: object; // 命名视图组件,H5端可用
|
||||
redirect?: string | Function; // H5端可用
|
||||
props?: boolean | object | Function; // H5端可用
|
||||
aliasPath?: string; // h5端 设置一个别名路径来替换 uni-app的默认路径
|
||||
alias?: string | Array<string>; // H5端可用
|
||||
children?: Array<RoutesRule>; // 嵌套路由,H5端可用
|
||||
beforeEnter?:guardHookRule; // 路由元守卫
|
||||
meta?: any; // 其他格外参数
|
||||
[propName: string]: any;
|
||||
}
|
||||
|
||||
export interface Router {
|
||||
[key:string]:any;
|
||||
readonly lifeCycle: LifeCycleConfig;
|
||||
readonly options: InstantiateConfig;
|
||||
$lockStatus:boolean;
|
||||
$route: object | null;
|
||||
enterPath:string;
|
||||
Vue:any;
|
||||
appProxyHook:{
|
||||
app:appVueHookConfig
|
||||
};
|
||||
appMain:{
|
||||
NAVTYPE:reNavMethodRule|reNotNavMethodRule,
|
||||
path:string
|
||||
}|{};
|
||||
appletsProxyHook:appletsVueHookConfig;
|
||||
routesMap: routesMapRule|{};
|
||||
mount: Array<{app: any; el: string}>;
|
||||
install(Vue: any): void;
|
||||
push(to: totalNextRoute|navRoute | string,from?:totalNextRoute): void; // 动态的导航到一个新 URL 保留浏览历史
|
||||
replace(to: totalNextRoute|navRoute | string,from?:totalNextRoute): void; // 动态的导航到一个新 URL 关闭当前页面,跳转到的某个页面。
|
||||
replaceAll(to: totalNextRoute|navRoute | string,from?:totalNextRoute): void; // 动态的导航到一个新 URL 关闭所有页面,打开到应用内的某个页面
|
||||
pushTab(to: totalNextRoute|navRoute | string,from?:totalNextRoute): void; // 动态的导航到一个新 url 关闭所有页面,打开到应用内的某个tab
|
||||
back(level:number|undefined,origin?:uniBackRule|uniBackApiRule):void;
|
||||
forceGuardEach(navType:NAVTYPE|undefined,forceNav:boolean):void; //强制触发当前守卫
|
||||
beforeEach(userGuard:guardHookRule): void; // 添加全局前置路由守卫
|
||||
afterEach(userGuard:(to: totalNextRoute, from: totalNextRoute)=>void): void; // 添加全局后置路由守卫
|
||||
}
|
||||
|
||||
|
||||
export type PromiseResolve=(value?: void | PromiseLike<void> | undefined) => void;
|
||||
|
||||
// @ts-ignore
|
||||
declare module 'vue/types/vue' {
|
||||
interface Vue {
|
||||
$Router: Router;
|
||||
$Route: routeRule;
|
||||
}
|
||||
}
|
||||
84
node_modules/uni-simple-router/src/options/config.ts
generated
vendored
Normal file
84
node_modules/uni-simple-router/src/options/config.ts
generated
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
import {startAnimationRule, hookListRule, RoutesRule, navtoRule, navErrorRule, Router, objectAny, hookObjectRule, NAVTYPE, totalNextRoute, navRoute} from './base';
|
||||
|
||||
export type debuggerConfig=boolean|debuggerArrayConfig;
|
||||
|
||||
export interface H5Config {
|
||||
paramsToQuery?: boolean; // h5端上通过params传参时规则是vue-router 刷新会丢失 开启此开关将变成?连接的方式
|
||||
vueRouterDev?: boolean; // 完全使用采用vue-router的开发模式
|
||||
vueNext?: boolean; // 在next管道函数中是否获取vueRouter next的原本参数
|
||||
mode?: string;
|
||||
base?: string;
|
||||
linkActiveClass?: string;
|
||||
linkExactActiveClass?: string;
|
||||
scrollBehavior?: Function;
|
||||
fallback?: boolean;
|
||||
}
|
||||
export interface AppConfig {
|
||||
registerLoadingPage?:boolean; // 是否注册过渡加载页 +v2.0.6
|
||||
loadingPageStyle?: () => object; // 当前等待页面的样式 必须返回一个json
|
||||
loadingPageHook?: (view:any)=>void; // 刚刚打开页面处于等待状态,会触发此函数
|
||||
launchedHook?:()=>void; // 首次启动app完成
|
||||
animation?: startAnimationRule; // 页面切换动画
|
||||
}
|
||||
export interface appletConfig {
|
||||
animationDuration?:number; // 页面切换时间,有助于路由锁精准解锁
|
||||
}
|
||||
|
||||
export interface debuggerArrayConfig{
|
||||
error?:boolean;
|
||||
warn?:boolean;
|
||||
log?:boolean;
|
||||
}
|
||||
|
||||
export interface InstantiateConfig {
|
||||
[key:string]:any;
|
||||
keepUniOriginNav?:boolean; // 重写uni-app的跳转方法;关闭后使用uni-app的原始方法跳转和插件api跳转等同
|
||||
platform:'h5'|'app-plus'|'app-lets'|'mp-weixin'|'mp-baidu'|'mp-alipay'|'mp-toutiao'|'mp-qq'|'mp-360'; // 当前运行平台
|
||||
h5?: H5Config;
|
||||
APP?: AppConfig;
|
||||
applet?:appletConfig;
|
||||
debugger?: debuggerConfig; // 是否处于开发阶段 设置为true则打印日志
|
||||
routerBeforeEach?: (to:navtoRule, from:navtoRule, next:(rule?: navtoRule|false)=>void) => void; // router 前置路由函数 每次触发跳转前先会触发此函数
|
||||
routerAfterEach?: (to:navtoRule, from:navtoRule, next?: Function) => void; // router 后置路由函数 每次触发跳转后会触发此函数
|
||||
routerErrorEach?: (error: navErrorRule, router:Router) => void;
|
||||
resolveQuery?:(jsonQuery:objectAny)=>objectAny; // 跳转之前把参数传递给此函数、返回最终的数据!有此函数不走默认方法
|
||||
parseQuery?:(jsonQuery:objectAny)=>objectAny; // 读取值之前把参数传递给此函数,返回最终的数据!有此函数不走默认方法
|
||||
detectBeforeLock?:(router:Router, to:string|number|totalNextRoute|navRoute, navType:NAVTYPE)=>void; // 在检测路由锁之前触发的函数
|
||||
routes: RoutesRule[];
|
||||
}
|
||||
export interface LifeCycleConfig{
|
||||
beforeHooks: hookListRule;
|
||||
afterHooks: hookListRule;
|
||||
routerBeforeHooks: hookListRule;
|
||||
routerAfterHooks: hookListRule;
|
||||
routerErrorHooks: Array<(error:navErrorRule, router:Router)=>void>;
|
||||
}
|
||||
|
||||
export interface baseAppHookConfig{
|
||||
[key:string]:Array<hookObjectRule|Function>;
|
||||
created:Array<hookObjectRule|Function>;
|
||||
beforeMount:Array<hookObjectRule|Function>;
|
||||
mounted:Array<hookObjectRule|Function>;
|
||||
beforeDestroy:Array<hookObjectRule|Function>;
|
||||
destroyed:Array<hookObjectRule|Function>;
|
||||
}
|
||||
|
||||
export interface appVueHookConfig extends baseAppHookConfig{
|
||||
onLaunch:Array<hookObjectRule|Function>;
|
||||
onShow:Array<hookObjectRule|Function>;
|
||||
onHide:Array<hookObjectRule|Function>;
|
||||
}
|
||||
export interface pageVueHookConfig extends baseAppHookConfig{
|
||||
onShow:Array<hookObjectRule|Function>;
|
||||
onHide:Array<hookObjectRule|Function>;
|
||||
onLoad:Array<hookObjectRule|Function>;
|
||||
onReady:Array<hookObjectRule|Function>;
|
||||
onUnload:Array<hookObjectRule|Function>;
|
||||
onResize:Array<hookObjectRule|Function>;
|
||||
}
|
||||
|
||||
export interface appletsVueHookConfig{
|
||||
app:appVueHookConfig;
|
||||
page:pageVueHookConfig,
|
||||
component:baseAppHookConfig[]
|
||||
}
|
||||
171
node_modules/uni-simple-router/src/public/hooks.ts
generated
vendored
Normal file
171
node_modules/uni-simple-router/src/public/hooks.ts
generated
vendored
Normal file
@@ -0,0 +1,171 @@
|
||||
import {
|
||||
Router,
|
||||
hookListRule,
|
||||
navtoRule,
|
||||
reloadNavRule,
|
||||
totalNextRoute,
|
||||
hookToggle,
|
||||
NAVTYPE,
|
||||
navErrorRule,
|
||||
objectAny
|
||||
} from '../options/base';
|
||||
import {
|
||||
routesForMapRoute,
|
||||
getDataType,
|
||||
forMatNextToFrom,
|
||||
getUniCachePage,
|
||||
voidFun
|
||||
} from '../helpers/utils'
|
||||
import { navjump } from './methods';
|
||||
import { proxyH5Mount } from '../H5/proxyHook';
|
||||
|
||||
export const ERRORHOOK:Array<(error:navErrorRule, router:Router)=>void> = [
|
||||
(error, router) => router.lifeCycle.routerErrorHooks[0](error, router)
|
||||
]
|
||||
export const HOOKLIST: hookListRule = [
|
||||
(router, to, from, toRoute, next) => callHook(router.lifeCycle.routerBeforeHooks[0], to, from, router, next),
|
||||
(router, to, from, toRoute, next) => callBeforeRouteLeave(router, to, from, next),
|
||||
(router, to, from, toRoute, next) => callHook(router.lifeCycle.beforeHooks[0], to, from, router, next),
|
||||
(router, to, from, toRoute, next) => callHook(toRoute.beforeEnter, to, from, router, next),
|
||||
(router, to, from, toRoute, next) => callHook(router.lifeCycle.afterHooks[0], to, from, router, next, false),
|
||||
(router, to, from, toRoute, next) => {
|
||||
router.$lockStatus = false;
|
||||
if (router.options.platform === 'h5') {
|
||||
proxyH5Mount(router);
|
||||
}
|
||||
return callHook(router.lifeCycle.routerAfterHooks[0], to, from, router, next, false)
|
||||
}
|
||||
];
|
||||
|
||||
export function callBeforeRouteLeave(
|
||||
router:Router,
|
||||
to:totalNextRoute,
|
||||
from:totalNextRoute,
|
||||
resolve:Function
|
||||
):void {
|
||||
const page = getUniCachePage<objectAny>(0);
|
||||
let beforeRouteLeave;
|
||||
if (Object.keys(page).length > 0) {
|
||||
let leaveHooks:Array<Function>|undefined|Function;
|
||||
if (router.options.platform === 'h5') {
|
||||
leaveHooks = (page as objectAny).$options.beforeRouteLeave;
|
||||
} else {
|
||||
if ((page as objectAny).$vm != null) {
|
||||
leaveHooks = (page as objectAny).$vm.$options.beforeRouteLeave;
|
||||
}
|
||||
}
|
||||
switch (getDataType<Array<Function>>((leaveHooks as Array<Function>))) {
|
||||
case '[object Array]': // h5端表现
|
||||
beforeRouteLeave = (leaveHooks as Array<Function>)[0];
|
||||
beforeRouteLeave = beforeRouteLeave.bind(page)
|
||||
break;
|
||||
case '[object Function]': // 目前app端表现
|
||||
beforeRouteLeave = (leaveHooks as Function).bind((page as objectAny).$vm);
|
||||
break
|
||||
}
|
||||
}
|
||||
return callHook(beforeRouteLeave, to, from, router, resolve);
|
||||
}
|
||||
|
||||
export function callHook(
|
||||
hook:Function|undefined,
|
||||
to:totalNextRoute,
|
||||
from: totalNextRoute,
|
||||
router:Router,
|
||||
resolve:Function,
|
||||
hookAwait:boolean|undefined = true
|
||||
):void {
|
||||
if (hook != null && hook instanceof Function) {
|
||||
if (hookAwait === true) {
|
||||
hook(to, from, resolve, router, false);
|
||||
} else {
|
||||
hook(to, from, () => {}, router, false);
|
||||
resolve();
|
||||
}
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
}
|
||||
|
||||
export function onTriggerEachHook(
|
||||
to:totalNextRoute,
|
||||
from: totalNextRoute,
|
||||
router:Router,
|
||||
hookType:hookToggle,
|
||||
next:(rule?: navtoRule|false)=>void,
|
||||
):void {
|
||||
let callHookList:hookListRule = [];
|
||||
switch (hookType) {
|
||||
case 'beforeEach':
|
||||
callHookList = HOOKLIST.slice(0, 3);
|
||||
break;
|
||||
case 'afterEach':
|
||||
callHookList = HOOKLIST.slice(4);
|
||||
break
|
||||
case 'beforeEnter':
|
||||
callHookList = HOOKLIST.slice(3, 4);
|
||||
break;
|
||||
}
|
||||
transitionTo(router, to, from, 'push', callHookList, next);
|
||||
}
|
||||
|
||||
export function transitionTo(
|
||||
router:Router,
|
||||
to:totalNextRoute,
|
||||
from: totalNextRoute,
|
||||
navType:NAVTYPE,
|
||||
callHookList:hookListRule,
|
||||
hookCB:Function
|
||||
) :void{
|
||||
const {matTo, matFrom} = forMatNextToFrom<totalNextRoute>(router, to, from);
|
||||
if (router.options.platform === 'h5') {
|
||||
loopCallHook(callHookList, 0, hookCB, router, matTo, matFrom, navType);
|
||||
} else {
|
||||
loopCallHook(callHookList.slice(0, 4), 0, () => {
|
||||
hookCB(() => { // 非H5端等他跳转完才触发最后两个生命周期
|
||||
loopCallHook(callHookList.slice(4), 0, voidFun, router, matTo, matFrom, navType);
|
||||
});
|
||||
}, router, matTo, matFrom, navType);
|
||||
}
|
||||
}
|
||||
|
||||
export function loopCallHook(
|
||||
hooks:hookListRule,
|
||||
index:number,
|
||||
next:Function,
|
||||
router:Router,
|
||||
matTo:totalNextRoute,
|
||||
matFrom: totalNextRoute,
|
||||
navType:NAVTYPE,
|
||||
): void|Function {
|
||||
const toRoute = routesForMapRoute(router, matTo.path, ['finallyPathMap', 'pathMap']);
|
||||
if (hooks.length - 1 < index) {
|
||||
return next();
|
||||
}
|
||||
const hook = hooks[index];
|
||||
const errHook = ERRORHOOK[0];
|
||||
hook(router, matTo, matFrom, toRoute, (nextTo:reloadNavRule) => {
|
||||
if (nextTo === false) {
|
||||
if (router.options.platform === 'h5') {
|
||||
next(false);
|
||||
}
|
||||
errHook({ type: 0, msg: '管道函数传递 false 导航被终止!', matTo, matFrom, nextTo }, router)
|
||||
} else if (typeof nextTo === 'string' || typeof nextTo === 'object') {
|
||||
let newNavType = navType;
|
||||
let newNextTo = nextTo;
|
||||
if (typeof nextTo === 'object') {
|
||||
const {NAVTYPE: type, ...moreTo} = nextTo;
|
||||
newNextTo = moreTo;
|
||||
if (type != null) {
|
||||
newNavType = type;
|
||||
}
|
||||
}
|
||||
navjump(newNextTo, router, newNavType, {from: matFrom, next})
|
||||
} else if (nextTo == null) {
|
||||
index++;
|
||||
loopCallHook(hooks, index, next, router, matTo, matFrom, navType)
|
||||
} else {
|
||||
errHook({ type: 1, msg: '管道函数传递未知类型,无法被识别。导航被终止!', matTo, matFrom, nextTo }, router)
|
||||
}
|
||||
});
|
||||
}
|
||||
255
node_modules/uni-simple-router/src/public/methods.ts
generated
vendored
Normal file
255
node_modules/uni-simple-router/src/public/methods.ts
generated
vendored
Normal file
@@ -0,0 +1,255 @@
|
||||
import {
|
||||
NAVTYPE,
|
||||
Router,
|
||||
totalNextRoute,
|
||||
objectAny,
|
||||
routeRule,
|
||||
reNavMethodRule,
|
||||
rewriteMethodToggle,
|
||||
navtypeToggle,
|
||||
navErrorRule,
|
||||
uniBackApiRule,
|
||||
uniBackRule,
|
||||
navRoute
|
||||
} from '../options/base'
|
||||
import {
|
||||
queryPageToMap,
|
||||
resolveQuery,
|
||||
parseQuery
|
||||
} from './query'
|
||||
import {
|
||||
voidFun,
|
||||
paramsToQuery,
|
||||
getUniCachePage,
|
||||
routesForMapRoute,
|
||||
copyData,
|
||||
lockDetectWarn,
|
||||
getDataType,
|
||||
reservedWord,
|
||||
notRouteTo404
|
||||
} from '../helpers/utils'
|
||||
import { transitionTo } from './hooks';
|
||||
import {createFullPath, createToFrom} from '../public/page'
|
||||
import {HOOKLIST} from './hooks'
|
||||
|
||||
export function lockNavjump(
|
||||
to:string|totalNextRoute|navRoute,
|
||||
router:Router,
|
||||
navType:NAVTYPE,
|
||||
forceNav?:boolean,
|
||||
animation?:uniBackApiRule|uniBackRule
|
||||
):void{
|
||||
lockDetectWarn(router, to, navType, () => {
|
||||
if (router.options.platform !== 'h5') {
|
||||
router.$lockStatus = true;
|
||||
}
|
||||
navjump(to as totalNextRoute, router, navType, undefined, forceNav, animation);
|
||||
});
|
||||
}
|
||||
export function navjump(
|
||||
to:string|totalNextRoute,
|
||||
router:Router,
|
||||
navType:NAVTYPE,
|
||||
nextCall?:{
|
||||
from:totalNextRoute;
|
||||
next:Function;
|
||||
},
|
||||
forceNav?:boolean,
|
||||
animation?:uniBackApiRule|uniBackRule,
|
||||
callHook:boolean|undefined = true
|
||||
) :void|never|totalNextRoute {
|
||||
if (navType === 'back') {
|
||||
let level:number = 1;
|
||||
if (typeof to === 'string') {
|
||||
level = +to;
|
||||
} else {
|
||||
level = to.delta || 1;
|
||||
}
|
||||
if (router.options.platform === 'h5') {
|
||||
(router.$route as any).go(-level);
|
||||
|
||||
// Fixe https://github.com/SilurianYang/uni-simple-router/issues/266 2021年6月3日11:14:38
|
||||
// @ts-ignore
|
||||
const success = (animation || {success: voidFun}).success || voidFun;
|
||||
// @ts-ignore
|
||||
const complete = (animation || {complete: voidFun}).complete || voidFun;
|
||||
success({errMsg: 'navigateBack:ok'});
|
||||
complete({errMsg: 'navigateBack:ok'});
|
||||
return;
|
||||
} else {
|
||||
to = backOptionsBuild(router, level, animation);
|
||||
}
|
||||
}
|
||||
to = reservedWord(to);
|
||||
const {rule} = queryPageToMap(to, router);
|
||||
rule.type = navtypeToggle[navType];
|
||||
const toRule = paramsToQuery(router, rule);
|
||||
let parseToRule = resolveQuery(toRule as totalNextRoute, router);
|
||||
if (router.options.platform === 'h5') {
|
||||
if (navType !== 'push') {
|
||||
navType = 'replace';
|
||||
}
|
||||
if (nextCall != null) { // next 管道函数拦截时 直接next即可
|
||||
nextCall.next({
|
||||
replace: navType !== 'push',
|
||||
...parseToRule
|
||||
})
|
||||
} else {
|
||||
// Fixe https://github.com/SilurianYang/uni-simple-router/issues/240 2021年3月7日14:45:36
|
||||
if (navType === 'push' && Reflect.has(parseToRule, 'events')) {
|
||||
if (Reflect.has(parseToRule, 'name')) {
|
||||
throw new Error(`在h5端上使用 'push'、'navigateTo' 跳转时,如果包含 events 不允许使用 name 跳转,因为 name 实现了动态路由。请更换为 path 或者 url 跳转!`);
|
||||
} else {
|
||||
uni['navigateTo'](parseToRule, true, voidFun, forceNav);
|
||||
}
|
||||
} else {
|
||||
(router.$route as any)[navType](parseToRule, (parseToRule as totalNextRoute).success || voidFun, (parseToRule as totalNextRoute).fail || voidFun)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let from:totalNextRoute = {path: ''};
|
||||
if (nextCall == null) {
|
||||
let toRoute = routesForMapRoute(router, parseToRule.path, ['finallyPathMap', 'pathMap']);
|
||||
toRoute = notRouteTo404(router, toRoute, parseToRule, navType);
|
||||
parseToRule = { ...toRoute, ...{params: {}}, ...parseToRule, ...{path: toRoute.path} }
|
||||
from = createToFrom(parseToRule, router);
|
||||
} else {
|
||||
from = nextCall.from;
|
||||
}
|
||||
createFullPath(parseToRule, from);
|
||||
if (callHook === false) {
|
||||
return parseToRule;
|
||||
}
|
||||
transitionTo(router, parseToRule, from, navType, HOOKLIST, function(
|
||||
callOkCb:Function
|
||||
):void {
|
||||
uni[navtypeToggle[navType]](parseToRule, true, callOkCb, forceNav);
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export function backOptionsBuild(
|
||||
router:Router,
|
||||
level:number,
|
||||
animation?:uniBackApiRule|uniBackRule,
|
||||
):totalNextRoute {
|
||||
const toRule = createRoute(router, level);
|
||||
const navjumpRule:totalNextRoute = {
|
||||
...animation || {},
|
||||
path: toRule.path,
|
||||
query: toRule.query,
|
||||
delta: level
|
||||
}
|
||||
if (getDataType<any>(animation) === '[object Object]') {
|
||||
const {animationDuration, animationType} = (animation as uniBackApiRule)
|
||||
if (animationDuration != null) {
|
||||
navjumpRule.animationDuration = animationDuration;
|
||||
}
|
||||
if (animationType != null) {
|
||||
navjumpRule.animationType = animationType;
|
||||
}
|
||||
|
||||
const {from} = (animation as uniBackRule)
|
||||
if (from != null) {
|
||||
navjumpRule.BACKTYPE = from;
|
||||
}
|
||||
}
|
||||
return navjumpRule;
|
||||
}
|
||||
|
||||
export function forceGuardEach(
|
||||
router:Router,
|
||||
navType:NAVTYPE|undefined = 'replaceAll',
|
||||
forceNav:undefined|boolean = false
|
||||
):void|never {
|
||||
if (router.options.platform === 'h5') {
|
||||
throw new Error(`在h5端上使用:forceGuardEach 是无意义的,目前 forceGuardEach 仅支持在非h5端上使用`);
|
||||
}
|
||||
const page = getUniCachePage<objectAny>(0);
|
||||
if (Object.keys(page).length === 0) {
|
||||
(router.options.routerErrorEach as (error: navErrorRule, router:Router) => void)({
|
||||
type: 3,
|
||||
msg: `不存在的页面栈,请确保有足够的页面可用,当前 level:0`
|
||||
}, router);
|
||||
}
|
||||
const {route, options} = page as objectAny;
|
||||
lockNavjump({
|
||||
path: `/${route}`,
|
||||
query: options
|
||||
}, router, navType, forceNav);
|
||||
}
|
||||
|
||||
export function createRoute(
|
||||
router:Router,
|
||||
level:number|undefined = 0,
|
||||
orignRule?:totalNextRoute,
|
||||
):routeRule|never {
|
||||
const route:routeRule = {
|
||||
name: '',
|
||||
meta: {},
|
||||
path: '',
|
||||
fullPath: '',
|
||||
NAVTYPE: '',
|
||||
query: {},
|
||||
params: {},
|
||||
BACKTYPE: (orignRule || {BACKTYPE: ''}).BACKTYPE || '' // v2.0.5 +
|
||||
};
|
||||
|
||||
if (level === 19970806) { // 首次构建响应式 页面不存在 直接返回
|
||||
return route
|
||||
}
|
||||
if (router.options.platform === 'h5') {
|
||||
let vueRoute:totalNextRoute = {path: ''};
|
||||
if (orignRule != null) {
|
||||
vueRoute = orignRule;
|
||||
} else {
|
||||
vueRoute = (router.$route as objectAny).currentRoute;
|
||||
}
|
||||
const matRouteParams = copyData(vueRoute.params as objectAny);
|
||||
delete matRouteParams.__id__;
|
||||
const toQuery = parseQuery({...matRouteParams, ...copyData(vueRoute.query as objectAny)}, router);
|
||||
vueRoute = {...vueRoute, query: toQuery}
|
||||
route.path = vueRoute.path;
|
||||
route.fullPath = vueRoute.fullPath || '';
|
||||
route.query = vueRoute.query || {};
|
||||
route.NAVTYPE = rewriteMethodToggle[vueRoute.type as reNavMethodRule || 'reLaunch'];
|
||||
} else {
|
||||
let appPage:objectAny = {};
|
||||
if (orignRule != null) {
|
||||
appPage = {...orignRule, openType: orignRule.type};
|
||||
} else {
|
||||
const page = getUniCachePage<objectAny>(level);
|
||||
if (Object.keys(page).length === 0) {
|
||||
(router.options.routerErrorEach as (error: navErrorRule, router:Router) => void)({
|
||||
type: 3,
|
||||
msg: `不存在的页面栈,请确保有足够的页面可用,当前 level:${level}`
|
||||
}, router);
|
||||
throw new Error(`不存在的页面栈,请确保有足够的页面可用,当前 level:${level}`)
|
||||
}
|
||||
// Fixes: https://github.com/SilurianYang/uni-simple-router/issues/196
|
||||
let pageOptions = (page as objectAny).options || {};
|
||||
const originQuery = pageOptions.query;
|
||||
if (originQuery != null && Object.keys(pageOptions).length === 1) {
|
||||
pageOptions = JSON.parse(decodeURIComponent(originQuery))
|
||||
}
|
||||
const pageQuery = JSON.parse(decodeURIComponent(JSON.stringify(pageOptions)))
|
||||
appPage = {
|
||||
...(page as objectAny).$page || {},
|
||||
query: pageQuery,
|
||||
fullPath: decodeURIComponent(((page as objectAny).$page || {}).fullPath || '/' + (page as objectAny).route)
|
||||
}
|
||||
if (router.options.platform !== 'app-plus') {
|
||||
appPage.path = `/${(page as objectAny).route}`
|
||||
}
|
||||
}
|
||||
const openType:reNavMethodRule|'navigateBack' = appPage.openType;
|
||||
route.query = appPage.query;
|
||||
route.path = appPage.path;
|
||||
route.fullPath = appPage.fullPath;
|
||||
route.NAVTYPE = rewriteMethodToggle[openType || 'reLaunch'];
|
||||
}
|
||||
const tableRoute = routesForMapRoute(router, route.path, ['finallyPathMap', 'pathMap'])
|
||||
const perfectRoute = { ...route, ...tableRoute};
|
||||
perfectRoute.query = parseQuery(perfectRoute.query, router);
|
||||
return perfectRoute;
|
||||
}
|
||||
41
node_modules/uni-simple-router/src/public/page.ts
generated
vendored
Normal file
41
node_modules/uni-simple-router/src/public/page.ts
generated
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
import { getDataType, getUniCachePage, deepClone, replaceHook} from '../helpers/utils';
|
||||
import { objectAny, pageTypeRule, Router, totalNextRoute } from '../options/base';
|
||||
import {createRoute} from './methods'
|
||||
import { stringifyQuery } from './query';
|
||||
|
||||
export function createToFrom(
|
||||
to:totalNextRoute,
|
||||
router:Router,
|
||||
):totalNextRoute {
|
||||
let fromRoute:totalNextRoute = {path: ''};
|
||||
const page = getUniCachePage<Array<any>|objectAny>(0);
|
||||
if (getDataType<Array<any>|objectAny>(page) === '[object Array]') {
|
||||
fromRoute = deepClone<totalNextRoute>(to)
|
||||
} else {
|
||||
fromRoute = createRoute(router) as totalNextRoute;
|
||||
}
|
||||
return fromRoute;
|
||||
}
|
||||
|
||||
export function createFullPath(
|
||||
to:totalNextRoute,
|
||||
from:totalNextRoute
|
||||
):void{
|
||||
if (to.fullPath == null) {
|
||||
const strQuery = stringifyQuery(to.query as objectAny);
|
||||
to.fullPath = to.path + strQuery;
|
||||
}
|
||||
if (from.fullPath == null) {
|
||||
const strQuery = stringifyQuery(from.query as objectAny);
|
||||
from.fullPath = from.path + strQuery;
|
||||
}
|
||||
}
|
||||
|
||||
export function proxyPageHook(
|
||||
vueVim:any,
|
||||
router:Router,
|
||||
proxyHookKey:'appProxyHook'|'appletsProxyHook',
|
||||
pageType:pageTypeRule,
|
||||
):void {
|
||||
replaceHook(router, vueVim, proxyHookKey, pageType);
|
||||
}
|
||||
200
node_modules/uni-simple-router/src/public/query.ts
generated
vendored
Normal file
200
node_modules/uni-simple-router/src/public/query.ts
generated
vendored
Normal file
@@ -0,0 +1,200 @@
|
||||
import {
|
||||
objectAny,
|
||||
Router,
|
||||
routesMapRule,
|
||||
RoutesRule,
|
||||
totalNextRoute
|
||||
} from '../options/base';
|
||||
import {
|
||||
getDataType,
|
||||
urlToJson,
|
||||
routesForMapRoute,
|
||||
getRoutePath,
|
||||
assertDeepObject,
|
||||
copyData,
|
||||
getWildcardRule
|
||||
} from '../helpers/utils'
|
||||
import {ERRORHOOK} from './hooks'
|
||||
import {warn} from '../helpers/warn'
|
||||
|
||||
const encodeReserveRE = /[!'()*]/g
|
||||
const encodeReserveReplacer = (c:string) => '%' + c.charCodeAt(0).toString(16)
|
||||
const commaRE = /%2C/g
|
||||
|
||||
const encode = (str:string) =>
|
||||
encodeURIComponent(str)
|
||||
.replace(encodeReserveRE, encodeReserveReplacer)
|
||||
.replace(commaRE, ',')
|
||||
|
||||
export function queryPageToMap(
|
||||
toRule:string|totalNextRoute,
|
||||
router:Router
|
||||
) :{
|
||||
rule:totalNextRoute;
|
||||
route:RoutesRule,
|
||||
query:objectAny
|
||||
} {
|
||||
let query:objectAny = {};
|
||||
let route:RoutesRule|string = '';
|
||||
let successCb = (toRule as totalNextRoute).success;
|
||||
let failCb = (toRule as totalNextRoute).fail;
|
||||
if (getDataType<string|totalNextRoute>(toRule) === '[object Object]') {
|
||||
const objNavRule = (toRule as totalNextRoute);
|
||||
if (objNavRule.path != null) {
|
||||
const {path, query: newQuery} = urlToJson(objNavRule.path);
|
||||
route = routesForMapRoute(router, path, ['finallyPathList', 'pathMap']);
|
||||
query = {...newQuery, ...((toRule as totalNextRoute).query || {})};
|
||||
objNavRule.path = path;
|
||||
objNavRule.query = query;
|
||||
delete (toRule as totalNextRoute).params;
|
||||
} else if (objNavRule.name != null) {
|
||||
route = (router.routesMap as routesMapRule).nameMap[objNavRule.name];
|
||||
if (route == null) {
|
||||
route = getWildcardRule(router, { type: 2, msg: `命名路由为:${objNavRule.name} 的路由,无法在路由表中找到!`, toRule});
|
||||
} else {
|
||||
query = (toRule as totalNextRoute).params || {};
|
||||
delete (toRule as totalNextRoute).query;
|
||||
}
|
||||
} else {
|
||||
route = getWildcardRule(router, { type: 2, msg: `${toRule} 解析失败,请检测当前路由表下是否有包含。`, toRule});
|
||||
}
|
||||
} else {
|
||||
toRule = urlToJson((toRule as string)) as totalNextRoute;
|
||||
route = routesForMapRoute(router, toRule.path, ['finallyPathList', 'pathMap'])
|
||||
query = toRule.query as objectAny;
|
||||
}
|
||||
if (router.options.platform === 'h5') {
|
||||
const {finallyPath} = getRoutePath(route as RoutesRule, router);
|
||||
if (finallyPath.includes(':') && (toRule as totalNextRoute).name == null) {
|
||||
ERRORHOOK[0]({ type: 2, msg: `当有设置 alias或者aliasPath 为动态路由时,不允许使用 path 跳转。请使用 name 跳转!`, route}, router)
|
||||
}
|
||||
const completeCb = (toRule as totalNextRoute).complete;
|
||||
const cacheSuccess = (toRule as totalNextRoute).success;
|
||||
const cacheFail = (toRule as totalNextRoute).fail;
|
||||
if (getDataType<Function|undefined>(completeCb) === '[object Function]') {
|
||||
const publicCb = function(this:any, args:Array<any>, callHook:Function|undefined):void {
|
||||
if (getDataType<Function|undefined>(callHook) === '[object Function]') {
|
||||
(callHook as Function).apply(this, args);
|
||||
}
|
||||
(completeCb as Function).apply(this, args);
|
||||
}
|
||||
successCb = function(this:any, ...args:any):void{
|
||||
publicCb.call(this, args, cacheSuccess);
|
||||
};
|
||||
failCb = function(this:any, ...args:any):void{
|
||||
publicCb.call(this, args, cacheFail);
|
||||
};
|
||||
}
|
||||
}
|
||||
const rule = (toRule as totalNextRoute);
|
||||
if (getDataType<Function|undefined>(rule.success) === '[object Function]') {
|
||||
rule.success = successCb;
|
||||
}
|
||||
if (getDataType<Function|undefined>(rule.fail) === '[object Function]') {
|
||||
rule.fail = failCb;
|
||||
}
|
||||
return {
|
||||
rule,
|
||||
route: (route as RoutesRule),
|
||||
query
|
||||
}
|
||||
}
|
||||
|
||||
export function resolveQuery(
|
||||
toRule:totalNextRoute,
|
||||
router:Router
|
||||
):totalNextRoute {
|
||||
let queryKey:'params'|'query' = 'query';
|
||||
if (toRule.params as objectAny != null) {
|
||||
queryKey = 'params';
|
||||
}
|
||||
if (toRule.query as objectAny != null) {
|
||||
queryKey = 'query';
|
||||
}
|
||||
const query = copyData(toRule[queryKey] || {});
|
||||
const {resolveQuery: userResolveQuery} = router.options;
|
||||
if (userResolveQuery) {
|
||||
const jsonQuery = userResolveQuery(query);
|
||||
if (getDataType<objectAny>(jsonQuery) !== '[object Object]') {
|
||||
warn('请按格式返回参数: resolveQuery?:(jsonQuery:{[propName: string]: any;})=>{[propName: string]: any;}', router)
|
||||
} else {
|
||||
toRule[queryKey] = jsonQuery;
|
||||
}
|
||||
} else {
|
||||
const deepObj = assertDeepObject(query as objectAny);
|
||||
if (!deepObj) {
|
||||
return toRule;
|
||||
}
|
||||
const encode = JSON.stringify(query);
|
||||
toRule[queryKey] = {
|
||||
query: encode
|
||||
}
|
||||
}
|
||||
return toRule
|
||||
}
|
||||
|
||||
export function parseQuery(
|
||||
query:objectAny,
|
||||
router:Router,
|
||||
):objectAny {
|
||||
const {parseQuery: userParseQuery} = router.options;
|
||||
if (userParseQuery) {
|
||||
query = userParseQuery(copyData(query));
|
||||
if (getDataType<objectAny>(query) !== '[object Object]') {
|
||||
warn('请按格式返回参数: parseQuery?:(jsonQuery:{[propName: string]: any;})=>{[propName: string]: any;}', router)
|
||||
}
|
||||
} else {
|
||||
if (Reflect.get(query, 'query')) { // 验证一下是不是深度对象
|
||||
const deepQuery = Reflect.get(query, 'query');
|
||||
let jsonQuery:objectAny = {
|
||||
query: decodeURIComponent(deepQuery)
|
||||
};
|
||||
try {
|
||||
jsonQuery = JSON.parse(jsonQuery.query);
|
||||
if (typeof jsonQuery === 'object') {
|
||||
return jsonQuery;
|
||||
}
|
||||
} catch (error) {
|
||||
warn('尝试解析深度对象失败,按原样输出。' + error, router)
|
||||
}
|
||||
}
|
||||
}
|
||||
return query
|
||||
}
|
||||
|
||||
export function stringifyQuery(obj:objectAny): string {
|
||||
const res = obj
|
||||
? Object.keys(obj)
|
||||
.map(key => {
|
||||
const val = obj[key]
|
||||
|
||||
if (val === undefined) {
|
||||
return ''
|
||||
}
|
||||
|
||||
if (val === null) {
|
||||
return encode(key)
|
||||
}
|
||||
|
||||
if (Array.isArray(val)) {
|
||||
const result:Array<any> = []
|
||||
val.forEach(val2 => {
|
||||
if (val2 === undefined) {
|
||||
return
|
||||
}
|
||||
if (val2 === null) {
|
||||
result.push(encode(key))
|
||||
} else {
|
||||
result.push(encode(key) + '=' + encode(val2))
|
||||
}
|
||||
})
|
||||
return result.join('&')
|
||||
}
|
||||
|
||||
return encode(key) + '=' + encode(val)
|
||||
})
|
||||
.filter(x => x.length > 0)
|
||||
.join('&')
|
||||
: null
|
||||
return res ? `?${res}` : ''
|
||||
}
|
||||
158
node_modules/uni-simple-router/src/public/rewrite.ts
generated
vendored
Normal file
158
node_modules/uni-simple-router/src/public/rewrite.ts
generated
vendored
Normal file
@@ -0,0 +1,158 @@
|
||||
import {
|
||||
uniNavApiRule,
|
||||
reNavMethodRule,
|
||||
reNotNavMethodRule,
|
||||
Router,
|
||||
rewriteMethodToggle,
|
||||
uniBackRule,
|
||||
uniBackApiRule,
|
||||
navtoRule,
|
||||
totalNextRoute,
|
||||
originMixins,
|
||||
objectAny
|
||||
} from '../options/base'
|
||||
|
||||
import {
|
||||
routesForMapRoute,
|
||||
getRoutePath,
|
||||
getDataType,
|
||||
notDeepClearNull,
|
||||
resolveAbsolutePath,
|
||||
getUniCachePage,
|
||||
timeOut
|
||||
} from '../helpers/utils'
|
||||
|
||||
import {
|
||||
warn
|
||||
} from '../helpers/warn'
|
||||
|
||||
import {uniOriginJump} from './uniOrigin'
|
||||
|
||||
const rewrite: Array<reNavMethodRule|reNotNavMethodRule> = [
|
||||
'navigateTo',
|
||||
'redirectTo',
|
||||
'reLaunch',
|
||||
'switchTab',
|
||||
'navigateBack'
|
||||
];
|
||||
|
||||
export function rewriteMethod(
|
||||
router:Router
|
||||
): void {
|
||||
if (router.options.keepUniOriginNav === false) {
|
||||
rewrite.forEach(name => {
|
||||
const oldMethod: Function = uni[name];
|
||||
uni[name] = function(
|
||||
params:originMixins|{from:string}|navtoRule,
|
||||
originCall:boolean = false,
|
||||
callOkCb?:Function,
|
||||
forceNav?:boolean
|
||||
):void {
|
||||
if (originCall) {
|
||||
uniOriginJump(router, oldMethod, name, params as originMixins, callOkCb, forceNav)
|
||||
} else {
|
||||
if (router.options.platform === 'app-plus') {
|
||||
if (Object.keys(router.appMain).length === 0) {
|
||||
router.appMain = {
|
||||
NAVTYPE: name,
|
||||
path: (params as uniNavApiRule).url
|
||||
}
|
||||
}
|
||||
}
|
||||
callRouterMethod(params as uniNavApiRule, name, router);
|
||||
}
|
||||
};
|
||||
})
|
||||
}
|
||||
}
|
||||
function callRouterMethod(
|
||||
option: uniNavApiRule|uniBackRule|uniBackApiRule,
|
||||
funName:reNavMethodRule|reNotNavMethodRule,
|
||||
router:Router
|
||||
): void {
|
||||
if (router.options.platform === 'app-plus') {
|
||||
let openType = null;
|
||||
if (option) {
|
||||
openType = (option as uniNavApiRule).openType;
|
||||
}
|
||||
if (openType != null && openType === 'appLaunch') {
|
||||
funName = 'reLaunch'
|
||||
}
|
||||
}
|
||||
if (funName === 'reLaunch' && JSON.stringify(option) === '{"url":"/"}') {
|
||||
warn(
|
||||
`uni-app 原生方法:reLaunch({url:'/'}) 默认被重写啦!你可以使用 this.$Router.replaceAll() 或者 uni.reLaunch({url:'/?xxx=xxx'})`,
|
||||
router,
|
||||
true
|
||||
);
|
||||
funName = 'navigateBack';
|
||||
option = {
|
||||
from: 'backbutton'
|
||||
}
|
||||
}
|
||||
if (funName === 'navigateBack') {
|
||||
let level:number = 1;
|
||||
if (option == null) {
|
||||
option = {delta: 1};
|
||||
}
|
||||
if (getDataType<number|undefined>((option as uniBackApiRule).delta) === '[object Number]') {
|
||||
level = ((option as uniBackApiRule).delta as number);
|
||||
}
|
||||
router.back(level, (option as uniBackRule|uniBackApiRule));
|
||||
} else {
|
||||
const routerMethodName = rewriteMethodToggle[(funName as reNavMethodRule)]
|
||||
let path = (option as uniNavApiRule).url;
|
||||
if (!path.startsWith('/')) {
|
||||
const absolutePath = resolveAbsolutePath(path, router);
|
||||
path = absolutePath;
|
||||
(option as uniNavApiRule).url = absolutePath;
|
||||
}
|
||||
if (funName === 'switchTab') {
|
||||
const route = routesForMapRoute(router, path, ['pathMap', 'finallyPathList'])
|
||||
const {finallyPath} = getRoutePath(route, router);
|
||||
if (getDataType<string | string[]>(finallyPath) === '[object Array]') {
|
||||
warn(
|
||||
`uni-app 原生方法跳转路径为:${path}。此路为是tab页面时,不允许设置 alias 为数组的情况,并且不能为动态路由!当然你可以通过通配符*解决!`,
|
||||
router,
|
||||
true
|
||||
);
|
||||
}
|
||||
if ((finallyPath as string) === '*') {
|
||||
warn(
|
||||
`uni-app 原生方法跳转路径为:${path}。在路由表中找不到相关路由表!当然你可以通过通配符*解决!`,
|
||||
router,
|
||||
true
|
||||
);
|
||||
}
|
||||
// Fixe h5 端无法触发 onTabItemTap hook 2021年6月3日17:26:47
|
||||
if (router.options.platform === 'h5') {
|
||||
const {success: userSuccess} = option as uniNavApiRule;
|
||||
(option as uniNavApiRule).success = (...args:Array<any>) => {
|
||||
userSuccess?.apply(null, args);
|
||||
timeOut(150).then(() => {
|
||||
const cbArgs = (option as uniNavApiRule).detail || {};
|
||||
if (Object.keys(cbArgs).length > 0 && Reflect.has(cbArgs, 'index')) {
|
||||
const cachePage = getUniCachePage(0);
|
||||
if (Object.keys(cachePage).length === 0) {
|
||||
return false
|
||||
}
|
||||
const page = cachePage as objectAny;
|
||||
const hooks = page.$options.onTabItemTap;
|
||||
if (hooks) {
|
||||
for (let j = 0; j < hooks.length; j++) {
|
||||
hooks[j].call(page, cbArgs)
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
path = (finallyPath as string);
|
||||
}
|
||||
const {events, success, fail, complete, animationType, animationDuration} = option as uniNavApiRule;
|
||||
const jumpOptions:totalNextRoute = {path, events, success, fail, complete, animationDuration, animationType};
|
||||
router[routerMethodName](
|
||||
notDeepClearNull<totalNextRoute>(jumpOptions)
|
||||
)
|
||||
}
|
||||
}
|
||||
122
node_modules/uni-simple-router/src/public/router.ts
generated
vendored
Normal file
122
node_modules/uni-simple-router/src/public/router.ts
generated
vendored
Normal file
@@ -0,0 +1,122 @@
|
||||
import {PromiseResolve, Router, uniBackApiRule, uniBackRule} from '../options/base';
|
||||
import {InstantiateConfig, LifeCycleConfig} from '../options/config';
|
||||
import {appProxyHook, indexProxyHook, lifeCycle, keyword} from '../helpers/config';
|
||||
import {assertNewOptions, def, getDataType} from '../helpers/utils';
|
||||
import {registerRouterHooks, registerEachHooks} from '../helpers/lifeCycle';
|
||||
import {initMixins} from '../helpers/mixins'
|
||||
import {lockNavjump, forceGuardEach, createRoute} from '../public/methods'
|
||||
import {rewriteMethod} from '../public/rewrite'
|
||||
|
||||
let AppReadyResolve:PromiseResolve = () => {};
|
||||
const AppReady:Promise<void> = new Promise(resolve => (AppReadyResolve = resolve));
|
||||
|
||||
function createRouter(params: InstantiateConfig):Router {
|
||||
const options = assertNewOptions<InstantiateConfig>(params);
|
||||
const router:Router = {
|
||||
options,
|
||||
mount: [],
|
||||
Vue: null,
|
||||
appProxyHook: appProxyHook,
|
||||
appletsProxyHook: indexProxyHook,
|
||||
appMain: {},
|
||||
enterPath: '',
|
||||
$route: null,
|
||||
$lockStatus: false,
|
||||
routesMap: {},
|
||||
lifeCycle: registerRouterHooks<LifeCycleConfig>(lifeCycle, options),
|
||||
push(to) {
|
||||
lockNavjump(to, router, 'push');
|
||||
},
|
||||
replace(to) {
|
||||
lockNavjump(to, router, 'replace');
|
||||
},
|
||||
replaceAll(to) {
|
||||
lockNavjump(to, router, 'replaceAll');
|
||||
},
|
||||
pushTab(to) {
|
||||
lockNavjump(to, router, 'pushTab');
|
||||
},
|
||||
back(level = 1, animation) {
|
||||
if (getDataType(animation) !== '[object Object]') {
|
||||
const backRule:uniBackRule = {
|
||||
from: 'navigateBack'
|
||||
}
|
||||
animation = backRule;
|
||||
} else {
|
||||
if (!Reflect.has((animation as uniBackRule | uniBackApiRule), 'from')) {
|
||||
animation = {
|
||||
...animation,
|
||||
from: 'navigateBack'
|
||||
};
|
||||
}
|
||||
}
|
||||
lockNavjump(level + '', router, 'back', undefined, animation)
|
||||
},
|
||||
forceGuardEach(navType, forceNav) {
|
||||
forceGuardEach(router, navType, forceNav)
|
||||
},
|
||||
beforeEach(userGuard):void {
|
||||
registerEachHooks(router, 'beforeHooks', userGuard);
|
||||
},
|
||||
afterEach(userGuard):void {
|
||||
registerEachHooks(router, 'afterHooks', userGuard);
|
||||
},
|
||||
install(Vue:any):void{
|
||||
router.Vue = Vue;
|
||||
rewriteMethod(this);
|
||||
initMixins(Vue, this);
|
||||
Object.defineProperty(Vue.prototype, '$Router', {
|
||||
get() {
|
||||
return router;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(Vue.prototype, '$Route', {
|
||||
get() {
|
||||
return createRoute(router);
|
||||
}
|
||||
});
|
||||
// 【Fixe】 https://github.com/SilurianYang/uni-simple-router/issues/254
|
||||
Object.defineProperty(Vue.prototype, '$AppReady', {
|
||||
get() {
|
||||
if (router.options.platform === 'h5') {
|
||||
return Promise.resolve();
|
||||
}
|
||||
return AppReady;
|
||||
},
|
||||
set(value:boolean) {
|
||||
if (value === true) {
|
||||
AppReadyResolve();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
def(router, 'keyword', () => keyword);
|
||||
def(router, 'currentRoute', () => createRoute(router));
|
||||
|
||||
router.beforeEach((to, from, next) => next());
|
||||
router.afterEach(() => {});
|
||||
return router;
|
||||
}
|
||||
|
||||
function RouterMount(Vim:any, router:Router, el:string | undefined = '#app') :void|never {
|
||||
if (getDataType<Array<any>>(router.mount) === '[object Array]') {
|
||||
router.mount.push({
|
||||
app: Vim,
|
||||
el
|
||||
})
|
||||
} else {
|
||||
throw new Error(`挂载路由失败,router.app 应该为数组类型。当前类型:${typeof router.mount}`);
|
||||
}
|
||||
if (router.options.platform === 'h5') {
|
||||
const vueRouter = (router.$route as any);
|
||||
vueRouter.replace({
|
||||
path: vueRouter.currentRoute.fullPath
|
||||
});
|
||||
} // 其他端目前不需要做啥
|
||||
}
|
||||
|
||||
export {
|
||||
RouterMount,
|
||||
createRouter
|
||||
}
|
||||
99
node_modules/uni-simple-router/src/public/uniOrigin.ts
generated
vendored
Normal file
99
node_modules/uni-simple-router/src/public/uniOrigin.ts
generated
vendored
Normal file
@@ -0,0 +1,99 @@
|
||||
import { originMixins, reNavMethodRule, reNotNavMethodRule, Router, startAnimationRule, uniNavApiRule } from '../options/base';
|
||||
import { stringifyQuery } from './query';
|
||||
import {notDeepClearNull, resetPageHook, timeOut} from '../helpers/utils'
|
||||
import { mpPlatformReg } from '../helpers/config';
|
||||
|
||||
let routerNavCount:number = 0;
|
||||
let lastNavType:reNavMethodRule|reNotNavMethodRule = 'reLaunch'
|
||||
|
||||
export function uniOriginJump(
|
||||
router:Router,
|
||||
originMethod:Function,
|
||||
funName:reNavMethodRule|reNotNavMethodRule,
|
||||
options: originMixins,
|
||||
callOkCb?:Function,
|
||||
forceNav?:boolean
|
||||
):void {
|
||||
const {complete, ...originRule} = formatOriginURLQuery(router, options, funName);
|
||||
const platform = router.options.platform.trim();
|
||||
if (routerNavCount === 0 && platform !== 'h5') { // 还原app.vue下已经重写后的生命周期
|
||||
resetPageHook(router, originRule.url)
|
||||
}
|
||||
if (forceNav != null && forceNav === false) {
|
||||
if (routerNavCount === 0) {
|
||||
routerNavCount++
|
||||
// 【Fixe】 https://github.com/SilurianYang/uni-simple-router/issues/254
|
||||
// 在小程序端 next 直接放行会执行这个
|
||||
if (platform !== 'h5') {
|
||||
router.Vue.prototype.$AppReady = true;
|
||||
}
|
||||
}
|
||||
complete && complete.apply(null, {msg: 'forceGuardEach强制触发并且不执行跳转'});
|
||||
callOkCb && callOkCb.apply(null, {msg: 'forceGuardEach强制触发并且不执行跳转'})
|
||||
} else {
|
||||
originMethod({
|
||||
...originRule,
|
||||
from: options.BACKTYPE,
|
||||
complete: async function(...args:Array<any>) {
|
||||
if (routerNavCount === 0) {
|
||||
routerNavCount++
|
||||
|
||||
// 【Fixe】 https://github.com/SilurianYang/uni-simple-router/issues/254
|
||||
// 在小程序端 第一次 next 做跳转 会触发这个 、在app端首次必定会触发这个
|
||||
if (platform !== 'h5') {
|
||||
router.Vue.prototype.$AppReady = true;
|
||||
}
|
||||
|
||||
if (platform === 'app-plus') {
|
||||
const waitPage = plus.nativeObj.View.getViewById('router-loadding');
|
||||
waitPage && waitPage.close();
|
||||
const launchedHook = router.options.APP?.launchedHook;
|
||||
launchedHook && launchedHook();
|
||||
}
|
||||
}
|
||||
let time:number = 0;
|
||||
if (new RegExp(mpPlatformReg, 'g').test(platform)) {
|
||||
time = (router.options.applet?.animationDuration) as number
|
||||
} else if (platform === 'app-plus') {
|
||||
if (funName === 'navigateBack' && lastNavType === 'navigateTo') {
|
||||
time = (router.options.APP?.animation?.animationDuration) as number
|
||||
}
|
||||
}
|
||||
if (funName === 'navigateTo' || funName === 'navigateBack') {
|
||||
if (time !== 0) {
|
||||
await timeOut(time);
|
||||
}
|
||||
}
|
||||
lastNavType = funName;
|
||||
complete && complete.apply(null, args);
|
||||
callOkCb && callOkCb.apply(null, args)
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
export function formatOriginURLQuery(
|
||||
router:Router,
|
||||
options:uniNavApiRule,
|
||||
funName:reNavMethodRule|reNotNavMethodRule
|
||||
):uniNavApiRule {
|
||||
const {url, path, query, animationType, animationDuration, events, success, fail, complete, delta, animation} = options;
|
||||
const strQuery = stringifyQuery(query || {});
|
||||
const queryURL = strQuery === '' ? (path || url) : (path || url) + strQuery;
|
||||
let animationRule:startAnimationRule = {};
|
||||
if (router.options.platform === 'app-plus') {
|
||||
if (funName !== 'navigateBack') {
|
||||
animationRule = router.options.APP?.animation || {};
|
||||
animationRule = {...animationRule, ...animation || {}};
|
||||
}
|
||||
}
|
||||
return notDeepClearNull<uniNavApiRule>({
|
||||
delta,
|
||||
url: queryURL,
|
||||
animationType: animationType || animationRule.animationType,
|
||||
animationDuration: animationDuration || animationRule.animationDuration,
|
||||
events,
|
||||
success,
|
||||
fail,
|
||||
complete
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user