参数改变时的Angular 2重载路由

问题描述 投票:39回答:11

我目前正在编写我的第一个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的重新初始化?

angular typescript angular2-routing
11个回答
33
投票

根据第一个最终版本,这已得到解决。

当参数改变时,要特别注意正确地重置组件的状态

this.route.params.subscribe(params => {
    this.param = params['yourParam'];
    this.initialiseState(); // reset and set based on new parameter this time
});

1
投票
this.route.paramMap.subscribe(params => {
  //fetch your new parameters here, on which you are switching the routes and call ngOnInit()
  this.ngOnInit();
 });

您只需要从paramMap中调用ngOnInit(),它将使用新加载的数据初始化整个页面。


-1
投票

在你的constructor()上使用它

this.router.routeReuseStrategy.shouldReuseRoute = () => false;

75
投票

您可以直接在组件级别更改routeReuseStrategy:

constructor(private router: Router) {

      // force route reload whenever params change;
      this.router.routeReuseStrategy.shouldReuseRoute = () => false;

}

同样,可以在全球范围内更改重用策略。

这不一定直接解决你的问题,但看看这个问题是第一个搜索结果“角度2重新加载URL如果查询参数更改”它可能会保存下一个人挖掘github问题。


9
投票

这里应该添加的另一个替代方法是为您的模块提供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


7
投票

我不知道这个问题的答案是否与我将要提出的问题相似,所以无论如何我都会这样做:

我设法通过以下方式实现'假'重装。

我基本上做的是创建一个组件,将我重定向到我想要使用的“真实”组件:

@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知识到达时,可能会有一些过渡来覆盖它。


5
投票

可以检测接收到的参数的任何变化,在我的情况下,我使用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();
  }
}

2
投票

我通过使用事件解决了它,如果子组件发送一个新的链接,并发出一个事件,那么父进程可以找到更改并调用一些重载函数,这将重新加载必要的数据。另一种选择是订阅route parameters, and found when it change但是我确实认为来自angular2的人应该考虑在router.navigate函数中添加参数,这可以强制重新加载。 (forceReload =真)


2
投票

希望这会有所帮助。

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);
    }
});

}

2
投票

Import Router in your Angular 7 project.

import { Router } from '@angular/router';

Create an object of the Router

constructor(private router: Router) {

}

Use routeReuseStrategy to detect router parameter change

ngOnInit() {
    this.router.routeReuseStrategy.shouldReuseRoute = () => {
      // do your task for before route

      return false;
    }
}

1
投票

目前尚未直接支持此功能。另见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;
  });
}

(未测试)

© www.soinside.com 2019 - 2024. All rights reserved.