我刚刚开始潜入来自Angular 1.5的Angular 4。我正在使用用户路由并将API数据从服务中提取到用户组件中。
该组件似乎保持静态。
无论如何是否可以在每个新路由请求上调用ngoninit函数?
我的用户组件类:
// url structure: /user/:id
export class UserComponent implements OnInit {
constructor(private route: ActivatedRoute) {}
ngOnInit() {
// doesn't log new id on route change
let id = this.route.snapshot.params['id'];
console.log(id);
this.route.params
.switchMap(params => this.userService.getUser(params['id']))
.subscribe(user => {
// logs new id on route change
let id = this.route.snapshot.params['id'];
console.log(id);
this.user = user
});
}
}
更新:
找到了我认为最适合我的情况的解决方案。根据对我的问题和进一步调查的几个答案和评论,订阅该路线似乎是必经之路。这是我更新的组件:
export class UserComponent {
user;
id;
constructor(
private userService: UserService,
private route: ActivatedRoute
) {}
ngOnInit() {
this.route.params
.subscribe(params => this.handleRouteChange(params));
}
handleRouteChange(params) {
this.id = params['id'];
switch (this.id) {
case '1':
console.log('User 1');
break;
case '2':
console.log('User 2');
break;
case '3':
console.log('User 3');
break;
}
this.userService.getUser(this.id).
subscribe(user => this.user = user);
}
}
Angular更喜欢 - 默认 - 重复使用相同的组件,而不是在路由相同但参数更改的情况下安装新组件。
。好消息!这是一种可自定义的行为,您可以通过实现自己的RouteReuseStrategy
来强制实施新组件实例:
export class MyRouteReuseStrategy extends DefaultRouteReuseStrategy {
shouldReuseRoute(next: ActivatedRouteSnapshot, current: ActivatedRouteSnapshot): boolean {
let name = next.component && (next.component as any).name;
return super.shouldReuseRoute(next, current) && name !== 'UserComponent';
}
}
在您的模块中:
@NgModule({
...
providers:[{
provide: RouteReuseStrategy,
useClass: MyRouteReuseStrategy}]
...
})
export class AppModule {}
(此代码或多或少是从本文中获取的,尤其是name
属性的支票,这可能不是很准确...(
请注意,重新制定同一组件时,这可能是某些性能弊端。因此,也许您最好使用可观察到的属性而不是快照。
我意识到这是事实之后,但我认为最好不要离开新来者可能在其项目中实施的不完整解决方案。
响应原始帖子的更新:重要的是,您必须在使用它们完成后取消订阅,否则您有可能将参考留在内存中。这是一个裸露的例子。
import { Component, OnInit, OnDestroy } from '@angular/core';
import { ActivatedRoute, Params } from '@angular/router';
import { Subscription, Observable } from 'rxjs';
@Component({
selector: 'app-example',
templateUrl: './example.component.html',
styleUrls: ['./example.component.scss']
})
export class Example implements OnInit, OnDestroy {
protected _routeChangeSubscription: Subscription;
constructor(
protected _activatedRoute: ActivatedRoute,
) { }
ngOnInit(): void {
this._routeChangeSubscription = this._activatedRoute.params.subscribe(this._routeChangeHandler);
}
ngOnDestroy(): void {
this._routeChangeSubscription.unsubscribe();
}
public _routeChangeHandler = (params: Observable<Params>) => {
// check params here
}
}
嗨,您必须使用 switchmap 这样:
this.sub = this.route.paramMap
.switchMap((params: ParamMap) =>
this.firebaseService.getProductsByCategory(params.get('category'))).subscribe(products => {
this.products = products;
this.count = products.length;
});
这项工作给我。
URL看起来像" ...?id = 1"或" ../:id",您希望每次获取param更改时组件登录ID?这个问题在这里谈论。我发现的一个更好的解决方案是在这里。我没有自己测试过,但这应该起作用。
第二个链接显示了如何订阅组件中的路由更改,我认为这实际上是您要做的。它将允许您处理ngOnInit
中的get param更改。我不确定当您最初导航到URL时,路由订阅是否会运行,因此您可能需要拥有处理路线事件的功能,将ngOnInit
调用为CC_5,更改为ngAfterContentInit
ngoninit仅在变更检测中运行,而变更似乎并没有触发它,这让我感到惊讶。
tl; dr-订阅构造函数中的路由更改事件,并创建一个处理发射事件的函数。该功能应保留您在ngoninit((中的逻辑。