为啥 routerLink 和 router.navigate() 行为不同?
Posted
技术标签:
【中文标题】为啥 routerLink 和 router.navigate() 行为不同?【英文标题】:Why routerLink and router.navigate() act differently?为什么 routerLink 和 router.navigate() 行为不同? 【发布时间】:2018-01-19 18:47:54 【问题描述】:在 html 中使用此代码时:
<button [routerLink]="[ outlets: flow: ['step1'] ]">click me to show step1</button>
它正确导航到'/child/(flow:step1)'!!!
尝试在 Typescript 中使用此代码时:
this.router.navigate([ outlets: flow: ['step1'] ]);
它试图导航到错误的路径'/child(flow:step1)'!!!
它只是缺少斜线。
服务:
import Injectable from '@angular/core';
import ActivatedRoute, Router from '@angular/router';
import EventBusService from '../../../services/eventBus/eventBus.service';
import RouterService from '../../../services/router.service';
@Injectable()
export class FlowManagerService
constructor(private router: Router, private r: ActivatedRoute, private eventBus: EventBusService, private routerService: RouterService)
initValidStep()
return (parseInt(this.routerService.currentUrlName.substr(this.routerService.currentUrlName.indexOf('step'), 5).replace('step', ''), 10) === 1);
goToFirstStep()
this.router.navigate([ outlets: flow: ['step1'] ], relativeTo: this.r);
this.eventBus.off(this.eventBus.globalEvents.FLOW.FLOW_STEP_NEXT);
this.eventBus.off(this.eventBus.globalEvents.FLOW.FLOW_STEP_BACK);
next(params)
const currentStep = this.routerService.currentUrlName.substr(this.routerService.currentUrlName.indexOf('step'), 5).replace('step', '');
this.eventBus.emit(this.eventBus.globalEvents.FLOW.FLOW_STEP_CHANGE, (
type: 'NEXT'
));
this.router.navigate([ outlets: flow: [`step$parseInt(currentStep, 10) + 1`, params] ], relativeTo: this.r);
this.eventBus.off(this.eventBus.globalEvents.FLOW.FLOW_STEP_NEXT);
this.eventBus.off(this.eventBus.globalEvents.FLOW.FLOW_STEP_BACK);
back(params)
const currentStep = this.routerService.currentUrlName.substr(this.routerService.currentUrlName.indexOf('step'), 5).replace('step', '');
this.eventBus.emit(this.eventBus.globalEvents.FLOW.FLOW_STEP_CHANGE, (
type: 'NEXT'
));
this.router.navigate([ outlets: flow: [`step$parseInt(currentStep, 10) - 1`, params] ], relativeTo: this.r);
this.eventBus.off(this.eventBus.globalEvents.FLOW.FLOW_STEP_NEXT);
this.eventBus.off(this.eventBus.globalEvents.FLOW.FLOW_STEP_BACK);
这是使用上述服务的模块:
import NgModule from '@angular/core';
import RouterModule from '@angular/router';
import FlowManagerService from './service/flowManager.service';
import CommonModule from '@angular/common';
@NgModule(
providers: [FlowManagerService],
imports: [
RouterModule,
CommonModule
]
)
export class FlowManagerModule
【问题讨论】:
【参考方案1】:因为routerLink
隐式使用relativeTo
选项:
export class RouterLink
...
get urlTree(): UrlTree
return this.router.createUrlTree(this.commands,
relativeTo: this.route, <----
您需要在router.navigate
中明确提供:
constructor(private route: ActivatedRoute)
this.router.navigate([ outlets: flow: ['step1'] ], relativeTo: this.route);
这是plunker 和完整的工作代码:
import Component, NgModule from '@angular/core'
import BrowserModule from '@angular/platform-browser'
import RouterModule, Routes, Resolve, Router, ActivatedRoute from '@angular/router';
import APP_BASE_HREF from '@angular/common';
@Component(
selector: 'my-app',
template: `
<div id='my-app'>
<router-outlet></router-outlet>
</div>
`,
)
export class App
constructor()
@Component(
selector: 'master-page',
template: `
<div id='master-page'>
<div>Master Component</div>
<button (click)='clickFirst()'>Inner Section 1</button>
<button (click)='clickSecond()'>Inner Section 2</button>
<router-outlet name='child'></router-outlet>
</div>
`
)
export class Master
constructor(private router: Router, private activeRouter: ActivatedRoute)
clickFirst()
this.router.navigate([outlets: child: 'details1'], relativeTo: this.activeRouter);
clickSecond()
this.router.navigate([outlets: child: 'details2'], relativeTo: this.activeRouter);
@Component(
template: `
<div>
This content is in the "Inner" page (1)
</div>
`
)
export class Details1
constructor()
@Component(
template: `
<div>
This content is in the "Inner" page (2)
</div>
`
)
export class Details2
constructor()
const routes: Routes = [
path: 'master',
component: Master,
children: [
path: 'details1',
component: Details1,
outlet: 'child'
,
path: 'details2',
component: Details2,
outlet: 'child'
]
,
path: '',
pathMatch: 'prefix',
redirectTo: 'master'
];
@NgModule(
imports: [BrowserModule, RouterModule.forRoot(routes)],
declarations: [App, Master, Details1, Details2],
providers: [
provide: APP_BASE_HREF,
useValue: '/'
],
bootstrap: [App]
)
export class AppModule
【讨论】:
你能设置一个 plunker 吗? link 这里...有一个基本插座和子插座...每次点击都应将组件插入一个子插座... @VladiIsakov,它对我来说很好用。在您的 plunker 中有一个错字,您应该使用outletS
,而不是 outlet
。我在问题中发布了有效的app.ts
代码。
抱歉打错了,也为我工作......在我的代码中它仍然无法工作......它说“错误:无法匹配任何路由。URL段:'step1'”
我没有看到你的代码。如示例所示,您的问题的答案是正确的以上是关于为啥 routerLink 和 router.navigate() 行为不同?的主要内容,如果未能解决你的问题,请参考以下文章
在Angular2 Dart中设置路由器和RouterLink的正确方法是啥