mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2026-03-13 10:22:08 +08:00
feat(router): adds redirectTo
This commit is contained in:
1
packages/core/src/components.d.ts
vendored
1
packages/core/src/components.d.ts
vendored
@@ -2604,6 +2604,7 @@ declare global {
|
||||
component?: string;
|
||||
params?: {[key: string]: any};
|
||||
path?: string;
|
||||
redirectTo?: string;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,11 @@ string
|
||||
string
|
||||
|
||||
|
||||
#### redirectTo
|
||||
|
||||
string
|
||||
|
||||
|
||||
## Attributes
|
||||
|
||||
#### component
|
||||
@@ -39,6 +44,11 @@ string
|
||||
string
|
||||
|
||||
|
||||
#### redirect-to
|
||||
|
||||
string
|
||||
|
||||
|
||||
|
||||
----------------------------------------------
|
||||
|
||||
|
||||
@@ -7,5 +7,6 @@ import { Component, Prop } from '@stencil/core';
|
||||
export class Route {
|
||||
@Prop() path = '';
|
||||
@Prop() component: string;
|
||||
@Prop() redirectTo: string;
|
||||
@Prop() params: {[key: string]: any};
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { Build, Component, Element, Listen, Method, Prop } from '@stencil/core';
|
||||
import { Config, DomController } from '../../index';
|
||||
import { flattenRouterTree, readRoutes } from './utils/parser';
|
||||
import { flattenRouterTree, readRoutes, readRedirects } from './utils/parser';
|
||||
import { readNavState, writeNavState } from './utils/dom';
|
||||
import { chainToPath, generatePath, parsePath, readPath, writePath } from './utils/path';
|
||||
import { RouteChain } from './utils/interfaces';
|
||||
import { routerIDsToChain, routerPathToChain } from './utils/matching';
|
||||
import { RouteChain, RouteRedirect } from './utils/interfaces';
|
||||
import { routerIDsToChain, routerPathToChain, routeRedirect } from './utils/matching';
|
||||
|
||||
|
||||
@Component({
|
||||
@@ -13,6 +13,7 @@ import { routerIDsToChain, routerPathToChain } from './utils/matching';
|
||||
export class Router {
|
||||
|
||||
private routes: RouteChain[];
|
||||
private redirects: RouteRedirect[];
|
||||
private busy = false;
|
||||
private state = 0;
|
||||
|
||||
@@ -28,6 +29,7 @@ export class Router {
|
||||
// read config
|
||||
const tree = readRoutes(this.el);
|
||||
this.routes = flattenRouterTree(tree);
|
||||
this.redirects = readRedirects(this.el);
|
||||
|
||||
if (Build.isDev) {
|
||||
console.debug('%c[@ionic/core]', 'font-weight: bold', `ion-router registered ${this.routes.length} routes`);
|
||||
@@ -42,7 +44,7 @@ export class Router {
|
||||
// perform first write
|
||||
this.dom.raf(() => {
|
||||
console.debug('[OUT] page load -> write nav state');
|
||||
this.writeNavStateRoot();
|
||||
this.onPopState();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -52,7 +54,7 @@ export class Router {
|
||||
this.state++;
|
||||
window.history.replaceState(this.state, document.title, document.location.href);
|
||||
}
|
||||
this.writeNavStateRoot();
|
||||
this.writeNavStateRoot(this.readPath());
|
||||
}
|
||||
|
||||
@Method()
|
||||
@@ -80,21 +82,23 @@ export class Router {
|
||||
|
||||
@Method()
|
||||
push(url: string, backDirection = false) {
|
||||
this.writePath(parsePath(url), backDirection);
|
||||
return this.writeNavStateRoot();
|
||||
const path = parsePath(url);
|
||||
this.writePath(path, backDirection);
|
||||
return this.writeNavStateRoot(path);
|
||||
}
|
||||
|
||||
private writeNavStateRoot(): Promise<any> {
|
||||
private writeNavStateRoot(path: string[]): Promise<any> {
|
||||
if (this.busy) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
const currentPath = this.readPath();
|
||||
if (!currentPath) {
|
||||
return Promise.resolve();
|
||||
const redirect = routeRedirect(path, this.redirects);
|
||||
if (redirect) {
|
||||
this.writePath(redirect.to, true);
|
||||
path = redirect.to;
|
||||
}
|
||||
const direction = window.history.state >= this.state ? 1 : -1;
|
||||
const node = document.querySelector('ion-app');
|
||||
const chain = routerPathToChain(currentPath, this.routes);
|
||||
const chain = routerPathToChain(path, this.routes);
|
||||
return this.writeNavState(node, chain, direction);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,11 @@ export interface NavOutlet {
|
||||
getContainerEl(): HTMLElement | null;
|
||||
}
|
||||
|
||||
export interface RouteRedirect {
|
||||
path: string[];
|
||||
to: string[];
|
||||
}
|
||||
|
||||
export interface RouteWrite {
|
||||
changed: boolean;
|
||||
markVisible?: () => void|Promise<void>;
|
||||
|
||||
@@ -1,4 +1,29 @@
|
||||
import { RouteChain, RouteID } from './interfaces';
|
||||
import { RouteChain, RouteID, RouteRedirect } from './interfaces';
|
||||
|
||||
|
||||
export function matchesRedirect(input: string[], route: RouteRedirect): boolean {
|
||||
const {path} = route;
|
||||
if (path.length !== input.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (let i = 0; i < path.length; i++) {
|
||||
if (path[i] !== input[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
export function routeRedirect(path: string[], routes: RouteRedirect[]): RouteRedirect|null {
|
||||
for (const route of routes) {
|
||||
if (matchesRedirect(path, route)) {
|
||||
return route;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
export function matchesIDs(ids: string[], chain: RouteChain): number {
|
||||
const len = Math.min(ids.length, chain.length);
|
||||
|
||||
@@ -1,10 +1,24 @@
|
||||
import { RouteChain, RouteNode, RouteTree } from './interfaces';
|
||||
import { RouteChain, RouteNode, RouteRedirect, RouteTree } from './interfaces';
|
||||
import { parsePath } from './path';
|
||||
|
||||
|
||||
export function readRedirects(root: Element): RouteRedirect[] {
|
||||
return (Array.from(root.children) as HTMLIonRouteElement[])
|
||||
.filter(el => el.tagName === 'ION-ROUTE' && el.redirectTo)
|
||||
.map(el => {
|
||||
if (el.component) {
|
||||
throw new Error('Can\'t mix the component and redirectTo attribute in the same ion-route');
|
||||
}
|
||||
return {
|
||||
path: parsePath(readProp(el, 'path')),
|
||||
to: parsePath(readProp(el, 'redirectTo'))
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
export function readRoutes(root: Element): RouteTree {
|
||||
return (Array.from(root.children) as HTMLIonRouteElement[])
|
||||
.filter(el => el.tagName === 'ION-ROUTE')
|
||||
.filter(el => el.tagName === 'ION-ROUTE' && el.component)
|
||||
.map(el => {
|
||||
const path = parsePath(readProp(el, 'path'));
|
||||
if (path.includes(':id')) {
|
||||
|
||||
Reference in New Issue
Block a user