mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-17 02:31:34 +08:00
134 lines
3.5 KiB
TypeScript
134 lines
3.5 KiB
TypeScript
import { generateId } from './utils';
|
|
import { pathToRegexp } from './regexp';
|
|
import { RouteInfo,
|
|
ViewItem,
|
|
ViewStacks,
|
|
} from './types';
|
|
import { RouteLocationMatched } from 'vue-router';
|
|
import { shallowRef } from 'vue';
|
|
|
|
export const createViewStacks = () => {
|
|
let viewStacks: ViewStacks = {};
|
|
|
|
const clear = (outletId: number) => {
|
|
delete viewStacks[outletId];
|
|
}
|
|
|
|
const getViewStack = (outletId: number) => {
|
|
return viewStacks[outletId];
|
|
}
|
|
|
|
const registerIonPage = (viewItem: ViewItem, ionPage: HTMLElement) => {
|
|
viewItem.ionPageElement = ionPage;
|
|
}
|
|
|
|
const findViewItemByRouteInfo = (routeInfo: RouteInfo, outletId?: number) => {
|
|
return findViewItemByPath(routeInfo.pathname, outletId);
|
|
}
|
|
|
|
const findLeavingViewItemByRouteInfo = (routeInfo: RouteInfo, outletId?: number) => {
|
|
return findViewItemByPath(routeInfo.lastPathname, outletId, false);
|
|
}
|
|
|
|
const findViewItemInStack = (path: string, stack: ViewItem[]): ViewItem | undefined => {
|
|
return stack.find((viewItem: ViewItem) => {
|
|
if (viewItem.pathname === path) {
|
|
return viewItem;
|
|
}
|
|
|
|
return undefined;
|
|
})
|
|
}
|
|
|
|
const findViewItemByPath = (path: string, outletId?: number, strict: boolean = true): ViewItem | undefined => {
|
|
const matchView = (viewItem: ViewItem) => {
|
|
const pathname = path;
|
|
const viewItemPath = viewItem.matchedRoute.path;
|
|
|
|
const regexp = pathToRegexp(viewItemPath, [], {
|
|
end: viewItem.exact,
|
|
strict: viewItem.exact,
|
|
sensitive: false
|
|
});
|
|
return (regexp.exec(pathname)) ? viewItem : undefined;
|
|
}
|
|
|
|
if (outletId) {
|
|
const stack = viewStacks[outletId];
|
|
if (!stack) return undefined;
|
|
|
|
const quickMatch = findViewItemInStack(path, stack);
|
|
if (quickMatch) return quickMatch;
|
|
|
|
if (!strict) {
|
|
const match = stack.find(matchView);
|
|
if (match) return match;
|
|
}
|
|
} else {
|
|
for (let outletId in viewStacks) {
|
|
const stack = viewStacks[outletId];
|
|
const viewItem = findViewItemInStack(path, stack);
|
|
if (viewItem) {
|
|
return viewItem;
|
|
}
|
|
}
|
|
}
|
|
|
|
return undefined;
|
|
}
|
|
|
|
const createViewItem = (outletId: number, vueComponent: any, matchedRoute: RouteLocationMatched, routeInfo: RouteInfo, ionPage?: HTMLElement): ViewItem => {
|
|
return {
|
|
id: generateId('viewItem'),
|
|
pathname: routeInfo.pathname,
|
|
outletId,
|
|
matchedRoute,
|
|
ionPageElement: ionPage,
|
|
vueComponent,
|
|
vueComponentRef: shallowRef(),
|
|
ionRoute: false,
|
|
mount: false,
|
|
exact: routeInfo.pathname === matchedRoute.path
|
|
};
|
|
}
|
|
|
|
const add = (viewItem: ViewItem): void => {
|
|
const { outletId } = viewItem;
|
|
if (!viewStacks[outletId]) {
|
|
viewStacks[outletId] = [viewItem];
|
|
} else {
|
|
viewStacks[outletId].push(viewItem);
|
|
}
|
|
}
|
|
|
|
const remove = (viewItem: ViewItem, outletId?: number): void => {
|
|
if (!outletId) { throw Error('outletId required') }
|
|
|
|
const viewStack = viewStacks[outletId];
|
|
if (viewStack) {
|
|
viewStacks[outletId] = viewStack.filter(item => item.id !== viewItem.id);
|
|
}
|
|
}
|
|
|
|
const getChildrenToRender = (outletId: number): ViewItem[] => {
|
|
const viewStack = viewStacks[outletId];
|
|
if (viewStack) {
|
|
const components = viewStacks[outletId].filter(v => v.mount);
|
|
return components;
|
|
}
|
|
return [];
|
|
}
|
|
|
|
return {
|
|
clear,
|
|
findViewItemByRouteInfo,
|
|
findLeavingViewItemByRouteInfo,
|
|
createViewItem,
|
|
getChildrenToRender,
|
|
add,
|
|
remove,
|
|
registerIonPage,
|
|
getViewStack
|
|
}
|
|
}
|