易货app

This commit is contained in:
唐明明
2021-07-21 14:36:42 +08:00
parent 607cb7f847
commit 17679fa432
49 changed files with 4289 additions and 7 deletions

76
node_modules/uni-simple-router/src/H5/buildRouter.ts generated vendored Normal file
View 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
View 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
View 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();
}
}
}

View 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
View 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
View 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
View 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'
];

View 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;
}

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
})
}