Router
配置信息
class Router {
constructor(rootComponentType: Type<any>, urlSerializer: UrlSerializer, rootContexts: ChildrenOutletContexts, location: Location, injector: Injector, loader: NgModuleFactoryLoader, compiler: Compiler, config: Routes)
// 在此NgModule中路由事件的事件流
events: Observable<Event>
// 當前的路由狀態
routerState: RouterState
errorHandler: ErrorHandler
malformedUriErrorHandler: (error: URIError, urlSerializer: UrlSerializer, url: string) => UrlTree
// 如果至少有一個導航事件發生,則爲True。默認false
navigated: boolean
// 提取和合並url的策略。
// 用於從AngularJS遷移到Angular。
urlHandlingStrategy: UrlHandlingStrategy
// 路由策略
routeReuseStrategy: RouteReuseStrategy
//forRoot 介紹過
onSameUrlNavigation: 'reload' | 'ignore'
// 如何從父路由到子路由合併參數
// 'emptyOnly' :爲無路徑或無組件路由繼承父參數,數據和已解析的數據。
// 'always' :繼承所有子路由的父參數,數據和已解析的數據。
paramsInheritanceStrategy: 'emptyOnly' | 'always'
// 定義路由器何時更新瀏覽器URL
// 默認 deferred 在成功導航後進行更新。如果希望在導航開始時更新URL
// eager 儘早更新URL,可以通過顯示帶有失敗URL的錯誤消息來處理導航失敗
urlUpdateStrategy: 'deferred' | 'eager'
//空路由的相對路由報錯修復機制,V11默認是corrected修復已有的 具體查看ExtraOptions
relativeLinkResolution: 'legacy' | 'corrected'
config: Routes
// 當前URL
url: string
initialNavigation(): void
setUpLocationChangeListener(): void
// 檢索最新的導航對象
getCurrentNavigation(): Navigation | null
// 重置用於導航和生成鏈接的路線配置。
resetConfig(config: Routes): void
dispose(): void
createUrlTree(commands: any[], navigationExtras: UrlCreationOptions = {}): UrlTree
// 路由絕對導航
navigateByUrl(url: string | UrlTree, extras: NavigationBehaviorOptions = {...}): Promise<boolean>
//路由相對導航
navigate(commands: any[], extras: NavigationExtras = { skipLocationChange: false }): Promise<boolean>
//把樹轉成絕對路徑的代碼
serializeUrl(url: UrlTree): string
// 輸入 url字符串返回 UrlTree類型
parseUrl(url: string): UrlTree
// 是否激活
isActive(url: string | UrlTree, exact: boolean): boolean
}
urlUpdateStrategy
定義路由器何時更新瀏覽器URL
'deferred' | 'eager'
eager 儘早更新URL,可以通過顯示帶有失敗URL的錯誤消息來處理導航失敗
export class TwoComponent implements OnInit {
constructor(
private router: Router,
private location: Location
) {
// router.urlUpdateStrategy = 'eager';
this.router.events.subscribe(e=>{
if (e instanceof NavigationStart) {
console.log(location.path());
}
// 當路由被識別時觸發的事件。
if(e instanceof RoutesRecognized){
console.log(location.path());
}
})
}
默認情況下返回的是上一個url
例如本來的路由是`/c`=> 跳轉 `/d`, 然後兩個都是返回的 `/c`
// 當設置 router.urlUpdateStrategy = 'eager' 儘早更新URL
那麼跳轉
NavigationStart 返回的上一個 `/c`
RoutesRecognized 返回的當前的 `/d`
Router.urlHandlingStrategy
提取和合並url的策略。
urlHandlingStrategy: UrlHandlingStrategy = new DefaultUrlHandlingStrategy();
// 提供了一種將AngularJS應用遷移到Angular的方法。
export class DefaultUrlHandlingStrategy implements UrlHandlingStrategy {
// 告訴路由器這個URL是否應該被處理。
// 當它返回true時,路由器將執行常規導航。
// 當返回false時,路由器將把路由器狀態設置爲空狀態。所有的活性成分都會被銷燬
shouldProcessUrl(url: UrlTree): boolean {
return true;
}
// 提取URL中應該由路由器處理的部分。URL的其餘部分將保持不變。
extract(url: UrlTree): UrlTree {
return url;
}
// 將URL片段與URL的其餘部分合並。
merge(newUrlPart: UrlTree, wholeUrl: UrlTree): UrlTree {
return newUrlPart;
}
}
案例
// 強制不處理URL更改
this.router.urlHandlingStrategy.shouldProcessUrl=(url:UrlTree)=> false;
// 我們發現設置之後所有的url的點擊跳轉都失效啦
this.router.navigateByUrl('/home/d')
Router.getCurrentNavigation()
Router.getCurrentNavigation() 方法檢索最新的導航對象
下面是關於導航操作的信息
type Navigation = {
// 當前導航的唯一標識符。
id: number;
// 導航前傳遞給調用的目標URL 。這是路由器解析或對其應用重定向之前的值
initialUrl: string | UrlTree;
// 使用解析後的初始目標
extractedUrl: UrlTree;
// 應用重定向後提取的URL。該網址可能不會立即可用,因此該屬性可以是undefined
finalUrl?: UrlTree;
// 觸發方式
// 'imperative'-由router.navigateByUrl或者觸發router.navigate
// 'popstate'-由popstate事件觸發。
// 'hashchange'-由hashchange事件觸發
trigger: 'imperative' | 'popstate' | 'hashchange';
// 用於控制用於此導航的策略。
extras: NavigationExtras;
// 先前成功的Navigation對象。只有一個先前的導航可用,因此該先前的Navigation對象具有null自己的值
previousNavigation: Navigation | null;
};
//修改Router導航策略的選項
interface NavigationExtras extends UrlCreationOptions, NavigationBehaviorOptions {
relativeTo?: ActivatedRoute | null
queryParams?: Params | null
fragment?: string
queryParamsHandling?: QueryParamsHandling | null
preserveFragment?: boolean
skipLocationChange?: boolean
replaceUrl?: boolean
state?: {...}
}
使用方法
constructor(
private viewport: ViewportScroller,
private router:Router
) {
router.events.subscribe(e => {
if (e instanceof NavigationEnd) {
console.log(router.getCurrentNavigation());
}
});
}
navigateByUrl
絕對路徑導航
navigateByUrl(
url: string|UrlTree,
extras: NavigationBehaviorOptions = {skipLocationChange: false}
): Promise<boolean>
export interface NavigationBehaviorOptions {
/**
爲true時,導航時不會將新狀態推入歷史記錄。
this.router.navigate(['/view'], { skipLocationChange: true });
*/
skipLocationChange?: boolean;
/**
當爲true時,在替換歷史中的當前狀態時進行導航
* this.router.navigate(['/view'], { replaceUrl: true });
*/
replaceUrl?: boolean;
/**
location.getState 可以查到
*/
state?: {[k: string]: any};
}
舉個小案例
const state = {foo: 'bar'};
router.navigateByUrl('/simple', {state});
//也可以類似多出口 router.navigateByUrl('/team/22/(user/victor//right:simple)');
路徑等於當前路徑時應替換狀態
// 點擊三次的狀態
router.navigateByUrl('/team/33/simple');
router.navigateByUrl('/team/22/user/victor');
router.navigateByUrl('/team/22/user/victor');
location.back();
// location.path() '/team/33/simple'
動態ID的技巧
{
path: 'd/:name', component: DComponent,
children: [
{path: 'a', component: AComponent},
{path: 'c/:age', component: CComponent, outlet: 'left'},
]
},
DComponent
<p>d works!</p>
<router-outlet></router-outlet>
<router-outlet name="left"></router-outlet>
this.router.navigateByUrl('/d/123/(a//left:c/123)')
只用left出口
this.router.navigateByUrl('/home/d/123/(left:c/123)')
// 這種情況
this.router.navigateByUrl('/home/d/123/a(left:F)')
// ()是這種在根路由添加一個left的新路由出口, 實際開發中用到的概率不高
父空路由多出口出現報錯的問題
path: '', component: TwoComponent, children: [
{path: 'a', component: AComponent},
{path: 'c', component: CComponent},
{
path: 'd', component: DComponent,
outlet: 'right'
},
]
TwoComponent的html記得導入出口
<router-outlet name="right"></router-outlet>
我們發現當使用 navigateByUrl會報錯
this.router.navigateByUrl('/(c//right:d)')
但是當我們父路由不是空路由就可以正常使用
{
path: 'd', component: DComponent,
children:[
{path: 'c', component: CComponent},
{path: 'a', component: AComponent,outlet:'right'},
]
},
this.router.navigateByUrl('/home/d/(c//right:a)')
這個時候如何解決這種問題呢?
其實我們可以嘗試使用navigate
, 然後我試過了,發現還是報錯,那麼暫時我思考的點
如果多出口的情況下,父路由不應該爲空
navigate
功能豐富的導航
navigate(
commands: any[],
extras: NavigationExtras = { skipLocationChange: false }
): Promise<boolean>
導航策略
interface NavigationExtras extends UrlCreationOptions, NavigationBehaviorOptions {
// inherited from router/UrlCreationOptions
relativeTo?: ActivatedRoute | null
queryParams?: Params | null
fragment?: string
queryParamsHandling?: QueryParamsHandling | null
preserveFragment?: boolean
// inherited from router/NavigationBehaviorOptions
skipLocationChange?: boolean
replaceUrl?: boolean
state?: {...}
}
案例
router.navigate(
['/a'],
{queryParams: {a: true}, queryParamsHandling: 'merge', replaceUrl: true});
相對的
router.navigate(['team', 33, 'user', 11], {relativeTo: route});
多入口
{path: 'c', component: CComponent,children:[
{path: 'd', component: DComponent,outlet:'left'},
{path: 'e', component: EComponent},
]},
router.navigate([{outlets: {left: 'd',primary:'e'}}], {relativeTo: this.route});
我們發現把值設置爲null,我們的left出口沒了
this.router.navigate([{outlets: {left: null,primary:'e'}}], {relativeTo: this.route});
// 當問號傳參設置的undefined/null
this.router.navigate(['/home/d'],{queryParams:{name:1,age:null,page:undefined}})
//結果 /home/d?name=1
動態id跳轉
[
{path: 'old/team/:id', redirectTo: 'team/:id'},
{path: 'team/:id', component: TeamCmp}
]
location.go('old/team/22');
// /team/22
resetConfig
重置用於導航和生成鏈接的路線配置。
記住重點**重置**和**生成**
export class OneComponent implements OnInit {
constructor(
private router:Router
) {
router.resetConfig([{path: 'show', component: DComponent}]);
}
clickDown() {
this.router.navigate(['/show']);
}
}
<a [routerLink]="['./c']">ccc</a> <br>
<a [routerLink]="['./d']">ddd</a> <br>
<button (click)="clickDown()">Click</button>
<p>
我們發現/show
可以跳轉,也就是新的導航, 之前的導航重置啦