Angular 5 - 路由更改 url 但不导航
Angular 5 - Routing changes url but doesn't navigate
目前我有三个不同的模块:
- 应用程序模块 -- 清空数组根配置
- 主页模块 -- 带有主页组件的“”路径配置。用于搜索玩家
- 玩家结果模块 -- 显示搜索结果(玩家统计或错误页面)
现在,在这个播放器搜索模块中,我有一个带有子组件的播放器搜索结果组件。其中一个子组件是一个带有列表的模式。如果我单击此列表项(播放器),它应该 'navigate' 到父组件并更新其视图。但唯一更新的是 url.
window.location.href(url)
有一个解决方法,即在导航方法更新 url 后重新加载页面。但我不喜欢变通办法。
父组件很像:
export class PlayerSearchResultComponent implements OnInit, AfterViewInit {
public isLoading = true;
public searchValue: string;
public playerResult: PlayerByPlayerTagType;
public hasNoResultFound = false;
public clanInfo: ClansByClantagType;
constructor(private playerSearchService: PlayerSearchService,
private activatedRoute: ActivatedRoute,
private clanSearchService: ClanSearchService) {
}
ngOnInit(): void {
this.activatedRoute.params.subscribe((params: Params) => {
this.searchValue = params['playerId'];
});
}
ngAfterViewInit() {
this.playerSearchService.getPlayerByPlayerTag(this.searchValue).subscribe(player => {
this.playerResult = player;
if (!isUndefined(this.playerResult.clan)) {
this.clanSearchService.getClanByClanTag(this.playerResult.clan.tag).subscribe((data: ClansByClantagType) => {
this.clanInfo = data;
});
}
}, () => {
this.hasNoResultFound = true;
this.isLoading = false;
},
() => this.isLoading = false);
}
}
和子组件:
export class ClanModalComponent {
@ViewChild('childModal') childModal: ModalDirective;
@Input() playerResult: PlayerByPlayerTagType;
@Input() clanInfo: ClansByClantagType;
constructor(private router: Router) {
}
open() {
this.childModal.show();
}
memberSearch(member) {
this.childModal.hide();
this.router.navigate(['search/' + member.tag]);
}
}
播放器结果模块如下所示:
const appRoutes: Routes = [
{path: 'search/:playerId', component: PlayerSearchResultComponent}
];
@NgModule({
declarations: [
...
],
imports: [
...
RouterModule.forChild(
appRoutes
)],
providers: [
...
],
exports: []
})
export class PlayerResultModule {
}
因此,要根据路由参数加载,您必须订阅路由参数并加载数据。 ngAfterViewInit 不会被再次处理。因为路由改变后组件不会再次加载!
ngOnInit(): void {
this.activatedRoute.params.subscribe((params: Params) => {
this.searchValue = params['playerId'];
this.playerSearchService
.getPlayerByPlayerTag(this.searchValue)
.subscribe(player => {
this.playerResult = player;
...
...
});
}
}
//browser is already on /pathName/oldID,
//this means our Routes are correct
let newLocation = `/pathName/${newID}`;
// override default re-use strategy
this.router
.routeReuseStrategy
.shouldReuseRoute = function () {
return false;
};
this.router
.navigateByUrl(newLocation)
.then(
(worked) => {
//works only because we hooked
//the routeReuseStrategy.shouldReuseRoute above
},
(error) => {
debugger;
}
);
我看到这个问题的次数比我愿意承认的要多,通常是在我有一个重用子组件的父容器时看到的。
- 父路由默认为xyz/。一切正常。
- 家长将路线更改为 xyz/1 以显示 1
的人员 ID 的详细信息
- 父页面只更改 url。
这是因为Angular的默认路由重用策略不会重新加载页面!
上面的代码修复了这个默认行为,但必须放入适当的组件才能从头开始重新加载行为。
请注意还有其他选择...假设您想要保持组件重用的速度。在这种情况下,只需提供一个进入已加载组件的入口点即可重置数据,让组件通过 changeDetectorRef.DetectChanges().
进行更改。
目前我有三个不同的模块:
- 应用程序模块 -- 清空数组根配置
- 主页模块 -- 带有主页组件的“”路径配置。用于搜索玩家
- 玩家结果模块 -- 显示搜索结果(玩家统计或错误页面)
现在,在这个播放器搜索模块中,我有一个带有子组件的播放器搜索结果组件。其中一个子组件是一个带有列表的模式。如果我单击此列表项(播放器),它应该 'navigate' 到父组件并更新其视图。但唯一更新的是 url.
window.location.href(url)
有一个解决方法,即在导航方法更新 url 后重新加载页面。但我不喜欢变通办法。
父组件很像:
export class PlayerSearchResultComponent implements OnInit, AfterViewInit {
public isLoading = true;
public searchValue: string;
public playerResult: PlayerByPlayerTagType;
public hasNoResultFound = false;
public clanInfo: ClansByClantagType;
constructor(private playerSearchService: PlayerSearchService,
private activatedRoute: ActivatedRoute,
private clanSearchService: ClanSearchService) {
}
ngOnInit(): void {
this.activatedRoute.params.subscribe((params: Params) => {
this.searchValue = params['playerId'];
});
}
ngAfterViewInit() {
this.playerSearchService.getPlayerByPlayerTag(this.searchValue).subscribe(player => {
this.playerResult = player;
if (!isUndefined(this.playerResult.clan)) {
this.clanSearchService.getClanByClanTag(this.playerResult.clan.tag).subscribe((data: ClansByClantagType) => {
this.clanInfo = data;
});
}
}, () => {
this.hasNoResultFound = true;
this.isLoading = false;
},
() => this.isLoading = false);
}
}
和子组件:
export class ClanModalComponent {
@ViewChild('childModal') childModal: ModalDirective;
@Input() playerResult: PlayerByPlayerTagType;
@Input() clanInfo: ClansByClantagType;
constructor(private router: Router) {
}
open() {
this.childModal.show();
}
memberSearch(member) {
this.childModal.hide();
this.router.navigate(['search/' + member.tag]);
}
}
播放器结果模块如下所示:
const appRoutes: Routes = [
{path: 'search/:playerId', component: PlayerSearchResultComponent}
];
@NgModule({
declarations: [
...
],
imports: [
...
RouterModule.forChild(
appRoutes
)],
providers: [
...
],
exports: []
})
export class PlayerResultModule {
}
因此,要根据路由参数加载,您必须订阅路由参数并加载数据。 ngAfterViewInit 不会被再次处理。因为路由改变后组件不会再次加载!
ngOnInit(): void {
this.activatedRoute.params.subscribe((params: Params) => {
this.searchValue = params['playerId'];
this.playerSearchService
.getPlayerByPlayerTag(this.searchValue)
.subscribe(player => {
this.playerResult = player;
...
...
});
}
}
//browser is already on /pathName/oldID,
//this means our Routes are correct
let newLocation = `/pathName/${newID}`;
// override default re-use strategy
this.router
.routeReuseStrategy
.shouldReuseRoute = function () {
return false;
};
this.router
.navigateByUrl(newLocation)
.then(
(worked) => {
//works only because we hooked
//the routeReuseStrategy.shouldReuseRoute above
},
(error) => {
debugger;
}
);
我看到这个问题的次数比我愿意承认的要多,通常是在我有一个重用子组件的父容器时看到的。
- 父路由默认为xyz/。一切正常。
- 家长将路线更改为 xyz/1 以显示 1 的人员 ID 的详细信息
- 父页面只更改 url。
这是因为Angular的默认路由重用策略不会重新加载页面!
上面的代码修复了这个默认行为,但必须放入适当的组件才能从头开始重新加载行为。
请注意还有其他选择...假设您想要保持组件重用的速度。在这种情况下,只需提供一个进入已加载组件的入口点即可重置数据,让组件通过 changeDetectorRef.DetectChanges().
进行更改。