259 lines
9.4 KiB
TypeScript
259 lines
9.4 KiB
TypeScript
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,
|
||
notRouteTo404,
|
||
deepDecodeQuery
|
||
} 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);
|
||
}, 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);
|
||
}
|
||
}
|
||
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|undefined = {},
|
||
):totalNextRoute {
|
||
const toRule = createRoute(router, level, undefined, {NAVTYPE: 'back', ...animation});
|
||
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 currentPage = getUniCachePage<objectAny>(0);
|
||
if (Object.keys(currentPage).length === 0) {
|
||
(router.options.routerErrorEach as (error: navErrorRule, router:Router) => void)({
|
||
type: 3,
|
||
NAVTYPE: navType,
|
||
uniActualData: {},
|
||
level: 0,
|
||
msg: `不存在的页面栈,请确保有足够的页面可用,当前 level:0`
|
||
}, router);
|
||
}
|
||
const {route, options} = currentPage as objectAny;
|
||
lockNavjump({
|
||
path: `/${route}`,
|
||
query: deepDecodeQuery(options || {})
|
||
}, router, navType, forceNav);
|
||
}
|
||
|
||
export function createRoute(
|
||
router:Router,
|
||
level:number|undefined = 0,
|
||
orignRule?:totalNextRoute,
|
||
uniActualData:objectAny|undefined = {},
|
||
):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 = deepDecodeQuery(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) {
|
||
const {NAVTYPE: _NAVTYPE, ..._args} = uniActualData;
|
||
const errorMsg:string = `不存在的页面栈,请确保有足够的页面可用,当前 level:${level}`;
|
||
(router.options.routerErrorEach as (error: navErrorRule, router:Router) => void)({
|
||
type: 3,
|
||
msg: errorMsg,
|
||
NAVTYPE: _NAVTYPE,
|
||
level,
|
||
uniActualData: _args
|
||
}, router);
|
||
throw new Error(errorMsg);
|
||
}
|
||
// Fixes: https://github.com/SilurianYang/uni-simple-router/issues/196
|
||
const pageOptions:objectAny = (page as objectAny).options || {};
|
||
appPage = {
|
||
...(page as objectAny).$page || {},
|
||
query: deepDecodeQuery(pageOptions),
|
||
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;
|
||
}
|