mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-18 03:00:58 +08:00
fix(router): route information is stateless
This commit is contained in:
@ -3,9 +3,9 @@ import { Config, QueueController } from '../../interface';
|
||||
import { debounce } from '../../utils/helpers';
|
||||
import { printRedirects, printRoutes } from './utils/debug';
|
||||
import { readNavState, waitUntilNavNode, writeNavState } from './utils/dom';
|
||||
import { RouteChain, RouteRedirect, RouterDirection, RouterEventDetail } from './utils/interface';
|
||||
import { RouteChain, RouterDirection, RouterEventDetail } from './utils/interface';
|
||||
import { routeRedirect, routerIDsToChain, routerPathToChain } from './utils/matching';
|
||||
import { flattenRouterTree, readRedirects, readRoutes } from './utils/parser';
|
||||
import { readRedirects, readRoutes } from './utils/parser';
|
||||
import { chainToPath, generatePath, parsePath, readPath, writePath } from './utils/path';
|
||||
|
||||
|
||||
@ -14,9 +14,7 @@ import { chainToPath, generatePath, parsePath, readPath, writePath } from './uti
|
||||
})
|
||||
export class Router {
|
||||
|
||||
private routes: RouteChain[] = [];
|
||||
private previousPath: string|null = null;
|
||||
private redirects: RouteRedirect[] = [];
|
||||
private busy = false;
|
||||
private state = 0;
|
||||
private lastState = 0;
|
||||
@ -59,17 +57,11 @@ export class Router {
|
||||
await waitUntilNavNode(this.win);
|
||||
console.debug('[ion-router] found nav');
|
||||
|
||||
const tree = readRoutes(this.el);
|
||||
this.routes = flattenRouterTree(tree);
|
||||
this.redirects = readRedirects(this.el);
|
||||
await this.onRoutesChanged();
|
||||
|
||||
this.win.addEventListener('ionRouteRedirectChanged', debounce(this.onRedirectChanged.bind(this), 10));
|
||||
this.win.addEventListener('ionRouteDataChanged', debounce(this.onRoutesChanged.bind(this), 100));
|
||||
|
||||
const changed = await this.writeNavStateRoot(this.getPath(), RouterDirection.None);
|
||||
if (!changed) {
|
||||
console.error('[ion-router] did not change on will load');
|
||||
}
|
||||
this.onRedirectChanged();
|
||||
}
|
||||
|
||||
@Listen('window:popstate')
|
||||
@ -81,17 +73,14 @@ export class Router {
|
||||
}
|
||||
|
||||
private onRedirectChanged() {
|
||||
this.redirects = readRedirects(this.el);
|
||||
const path = this.getPath();
|
||||
if (path && routeRedirect(path, this.redirects)) {
|
||||
if (path && routeRedirect(path, readRedirects(this.el))) {
|
||||
this.writeNavStateRoot(path, RouterDirection.None);
|
||||
}
|
||||
}
|
||||
|
||||
private onRoutesChanged() {
|
||||
const tree = readRoutes(this.el);
|
||||
this.routes = flattenRouterTree(tree);
|
||||
this.writeNavStateRoot(this.getPath(), RouterDirection.None);
|
||||
return this.writeNavStateRoot(this.getPath(), RouterDirection.None);
|
||||
}
|
||||
|
||||
private historyDirection() {
|
||||
@ -117,8 +106,8 @@ export class Router {
|
||||
printDebug() {
|
||||
console.debug('CURRENT PATH', this.getPath());
|
||||
console.debug('PREVIOUS PATH', this.previousPath);
|
||||
printRoutes(this.routes);
|
||||
printRedirects(this.redirects);
|
||||
printRoutes(readRoutes(this.el));
|
||||
printRedirects(readRedirects(this.el));
|
||||
}
|
||||
|
||||
@Method()
|
||||
@ -127,7 +116,8 @@ export class Router {
|
||||
return false;
|
||||
}
|
||||
const { ids, outlet } = readNavState(this.win.document.body);
|
||||
const chain = routerIDsToChain(ids, this.routes);
|
||||
const routes = readRoutes(this.el);
|
||||
const chain = routerIDsToChain(ids, routes);
|
||||
if (!chain) {
|
||||
console.warn('[ion-router] no matching URL for ', ids.map(i => i.id));
|
||||
return false;
|
||||
@ -149,9 +139,9 @@ export class Router {
|
||||
@Method()
|
||||
push(url: string, direction = RouterDirection.Forward) {
|
||||
const path = parsePath(url);
|
||||
this.setPath(path, direction);
|
||||
|
||||
console.debug('[ion-router] URL pushed -> updating nav', url, direction);
|
||||
|
||||
this.setPath(path, direction);
|
||||
return this.writeNavStateRoot(path, direction);
|
||||
}
|
||||
|
||||
@ -165,16 +155,18 @@ export class Router {
|
||||
}
|
||||
|
||||
// lookup redirect rule
|
||||
const redirect = routeRedirect(path, this.redirects);
|
||||
const redirects = readRedirects(this.el);
|
||||
const redirect = routeRedirect(path, redirects);
|
||||
let redirectFrom: string[]|null = null;
|
||||
if (redirect) {
|
||||
this.setPath(redirect.to!, direction);
|
||||
this.setPath(redirect.to, direction);
|
||||
redirectFrom = redirect.from;
|
||||
path = redirect.to!;
|
||||
path = redirect.to;
|
||||
}
|
||||
|
||||
// lookup route chain
|
||||
const chain = routerPathToChain(path, this.routes);
|
||||
const routes = readRoutes(this.el);
|
||||
const chain = routerPathToChain(path, routes);
|
||||
if (!chain) {
|
||||
console.error('[ion-router] the path does not match any route');
|
||||
return false;
|
||||
|
@ -19,7 +19,7 @@ export const enum RouterDirection {
|
||||
|
||||
export interface RouteRedirect {
|
||||
from: string[];
|
||||
to: string[]|undefined;
|
||||
to?: string[];
|
||||
}
|
||||
|
||||
export interface RouteWrite {
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { RouteChain, RouteID, RouteRedirect } from './interface';
|
||||
|
||||
|
||||
export function matchesRedirect(input: string[], route: RouteRedirect): boolean {
|
||||
export function matchesRedirect(input: string[], route: RouteRedirect): route is Required<RouteRedirect> {
|
||||
const {from, to} = route;
|
||||
if (to === undefined) {
|
||||
return false;
|
||||
@ -23,13 +23,8 @@ export function matchesRedirect(input: string[], route: RouteRedirect): boolean
|
||||
return from.length === input.length;
|
||||
}
|
||||
|
||||
export function routeRedirect(path: string[], routes: RouteRedirect[]): RouteRedirect|null {
|
||||
for (const route of routes) {
|
||||
if (matchesRedirect(path, route)) {
|
||||
return route;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
export function routeRedirect(path: string[], routes: RouteRedirect[]) {
|
||||
return routes.find(route => matchesRedirect(path, route)) as Required<RouteRedirect> | undefined;
|
||||
}
|
||||
|
||||
|
||||
|
@ -14,7 +14,11 @@ export function readRedirects(root: Element): RouteRedirect[] {
|
||||
});
|
||||
}
|
||||
|
||||
export function readRoutes(root: Element, node = root): RouteTree {
|
||||
export function readRoutes(root: Element): RouteChain[] {
|
||||
return flattenRouterTree(readRouteNodes(root));
|
||||
}
|
||||
|
||||
export function readRouteNodes(root: Element, node = root): RouteTree {
|
||||
return (Array.from(node.children) as HTMLIonRouteElement[])
|
||||
.filter(el => el.tagName === 'ION-ROUTE' && el.component)
|
||||
.map(el => {
|
||||
@ -26,7 +30,7 @@ export function readRoutes(root: Element, node = root): RouteTree {
|
||||
path: parsePath(readProp(el, 'url')),
|
||||
id: component.toLowerCase(),
|
||||
params: el.componentProps,
|
||||
children: readRoutes(root, el)
|
||||
children: readRouteNodes(root, el)
|
||||
};
|
||||
});
|
||||
}
|
||||
|
Reference in New Issue
Block a user