我目前正在编写我的第一个Angular 2应用程序。我有一个OverviewComponent,它有以下简单的模板:
<div class="row">
<div class="col-lg-8">
<router-outlet></router-outlet>
</div>
<div class="col-lg-4">
<app-list></app-list>
</div>
</div>
当访问网址/
时,我的路由器将我重定向到/overview
,然后在路由器插座内加载地图。 <app-list>
有一个可点击项目列表,触发显示<app-detail>
而不是app组件。因此我在url中传递引用json文件的id,如:/details/:id
(在我的路由中)。
所有上述工作完全没问题。如果我现在单击其中一个列表项,则显示详细信息,但是当我选择另一个列表元素时,视图不会更改为新的详细信息。 URL确实更改但内容未重新加载。如何实现DetailComponent的重新初始化?
根据第一个最终版本,这已得到解决。
当参数改变时,要特别注意正确地重置组件的状态
this.route.params.subscribe(params => {
this.param = params['yourParam'];
this.initialiseState(); // reset and set based on new parameter this time
});
this.route.paramMap.subscribe(params => {
//fetch your new parameters here, on which you are switching the routes and call ngOnInit()
this.ngOnInit();
});
您只需要从paramMap中调用ngOnInit(),它将使用新加载的数据初始化整个页面。
在你的constructor()
上使用它
this.router.routeReuseStrategy.shouldReuseRoute = () => false;
您可以直接在组件级别更改routeReuseStrategy:
constructor(private router: Router) {
// force route reload whenever params change;
this.router.routeReuseStrategy.shouldReuseRoute = () => false;
}
同样,可以在全球范围内更改重用策略。
这不一定直接解决你的问题,但看看这个问题是第一个搜索结果“角度2重新加载URL如果查询参数更改”它可能会保存下一个人挖掘github问题。
这里应该添加的另一个替代方法是为您的模块提供RouteReuseStrategy。
providers: [
{
provide: RouteReuseStrategy,
useClass: AARouteReuseStrategy
}
]
如果配置相同,则路由器的默认行为是重用路由(在此问题中仅更改:id参数时就是这种情况)。通过将策略更改为不重用路由,将重新加载组件,并且您不必订阅组件中的路由更改。
RouteReuseStrategy的实现可能是这样的:
export class AARouteReuseStrategy extends RouteReuseStrategy {
shouldDetach(route: ActivatedRouteSnapshot): boolean {
return false;
}
store(route: ActivatedRouteSnapshot, handle: {}): void {
}
shouldAttach(route: ActivatedRouteSnapshot): boolean {
return false;
}
retrieve(route: ActivatedRouteSnapshot): {} {
return null;
}
shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
return false; // default is true if configuration of current and future route are the same
}
}
我也在这里写了一些关于它的文章:
https://pjsjava.blogspot.no/2018/01/angular-components-not-reloading-on.html
我不知道这个问题的答案是否与我将要提出的问题相似,所以无论如何我都会这样做:
我设法通过以下方式实现'假'重装。
我基本上做的是创建一个组件,将我重定向到我想要使用的“真实”组件:
@Component({
selector: 'camps-fake',
template: ''
})
export class FakeComponent implements OnInit {
constructor(private _router:Router,
private _route:ActivatedRoute)
{ }
ngOnInit() {
let id:number = -1;
this._route.params.forEach((params:Params) => {
id = +params['id'];
});
let link:any[] = ['/details', id];
this._router.navigate(link);
}
}
因此,通过选择列表项,路由器将导航到/fake/:id
,它只是从URL中提取id并导航到“真实”组件。
我知道可能有一种更简单,或更花哨的方式,但我认为这种解决方案效果很好,因为假的并没有引起人们的注意。当页面重新加载时只是“闪烁”是一个消极方面,但就我的css知识到达时,可能会有一些过渡来覆盖它。
可以检测接收到的参数的任何变化,在我的情况下,我使用Resolve加载信息,所以我不需要参数(只检测它是否改变)。这是我的最终解决方案:
public product: Product;
private parametersObservable: any;
constructor(private route: ActivatedRoute) {
}
ngOnInit() {
this.parametersObservable = this.route.params.subscribe(params => {
//"product" is obtained from 'ProductResolver'
this.product = this.route.snapshot.data['product'];
});
}
//Don't forget to unsubscribe from the Observable
ngOnDestroy() {
if(this.parametersObservable != null) {
this.parametersObservable.unsubscribe();
}
}
我通过使用事件解决了它,如果子组件发送一个新的链接,并发出一个事件,那么父进程可以找到更改并调用一些重载函数,这将重新加载必要的数据。另一种选择是订阅route parameters, and found when it change但是我确实认为来自angular2的人应该考虑在router.navigate函数中添加参数,这可以强制重新加载。 (forceReload =真)
希望这会有所帮助。
constructor(private router: Router){
// override the route reuse strategy
this.router.routeReuseStrategy.shouldReuseRoute = function(){
return false;
}
this.router.events.subscribe((evt) => {
if (evt instanceof NavigationEnd) {
// trick the Router into believing it's last link wasn't previously loaded
this.router.navigated = false;
// if you need to scroll back to top, here is the right place
window.scrollTo(0, 0);
}
});
}
import { Router } from '@angular/router';
constructor(private router: Router) {
}
ngOnInit() {
this.router.routeReuseStrategy.shouldReuseRoute = () => {
// do your task for before route
return false;
}
}
目前尚未直接支持此功能。另见https://github.com/angular/angular/issues/9811
你能做的就像是
<div *ngIf="doShow" class="row">
<div class="col-lg-8">
<router-outlet></router-outlet>
</div>
<div class="col-lg-4">
<app-list></app-list>
</div>
</div>
doShow:boolean: true;
constructor(private _activatedRoute: ActivatedRoute, private _router:Router, private cdRef:ChangeDetectorRef) {
_router.routerState.queryParams.subscribe(
data => {
console.log('queryParams', data['st']);
this.doShow = false;
this.cdRef.detectChanges();
this.doShow = true;
});
}
(未测试)