停止在路线更改时重新加载整个内容

时间:2016-08-20 13:25:48

标签: javascript angularjs angular typescript angular-routing

我有以下路线:page/:id,其中为每个id加载不同的内容。但是,每次我转到不同的页面时,它都会重新加载整个内容。我只想重新加载来自API的数据。

导航:

<ul>
 <li [routerLink]="['/page', 1]">Page 1</li>
 <li [routerLink]="['/page', 2]">Page 2</li>
 <li [routerLink]="['/page', 3]">Page 3</li>
</ul>

模板: <h1 *ngIf="data">{{data.name}}</h1>

组件:

export class DataComponent implements OnInit {

  data: any;
  error: any;

  constructor(
    private route: ActivatedRoute,
    private service: DataService
  ) {}

  ngOnInit() {
    this.getData();
  }

  getData() {
    this.service.getData()
      .subscribe(
        res => this.data = res,
        error => this.error = error
      );
  }

}

如果您转到此Plunker,每次路线更改时,您都会看到黑色矩形闪烁。理想情况下,黑色部分将保持不变,只有内部数据会发生变化。

我也注意到这种闪烁行为只有在我使用HTTP调用时才会发生。如果我在该组件中有其他东西,那么在更改路径时就不会发生这种情况。

关于如何解决这个问题的任何想法?

编辑Here's a Plunkr显示预期的行为。但是,我使用的是前ROUTER_DIRECTIVES,现已弃用。

3 个答案:

答案 0 :(得分:1)

您的闪烁发生是因为导航时DataComponent被销毁并重新构建,但在新数据从服务器到达之前无法显示,因为您使用*ngIf="data"阻止其显示。 On this plunker,我在服务器响应中添加了1秒的延迟,以使问题显而易见。请注意,只有DataComponent闪烁。 PagesComponent的其余部分没有。

On this plunker,没有可见的闪烁,因为数据是硬编码的,因此不会等待服务器的响应。

为了减轻眨眼,请不要使用*ngIf,因为它会完全从dom中删除元素。 On this plunker,即使我们等待数据从服务器到达,也不会发生闪烁。

基本上,只要您选择隐藏元素直到数据到达,无论何时重新初始化组件,您都会看到闪烁。

答案 1 :(得分:0)

您刚刚重新加载来自API的内容。黑框闪烁,因为您正在为h1设置样式并且h1正在发生变化。如果您希望每个页面都显示该框,请将其移至AppComponent模板。

<div class="box">
    <router-outlet></router-outlet>
</div>

然后将样式移至.box选择器而不是h1

另一个问题是,在删除和刷新内容时,框的高度将会折叠和展开。您可以通过在路线上使用解决方案来解决此问题。

https://angular.io/docs/ts/latest/guide/router.html#!#resolve-guard

答案 2 :(得分:0)

扩展@ Rob的答案,我确实设法使用Resolve后卫解决了这个问题。但是,我在实施过程中犯了一些错误。

我已经创建了一个新的data-resolve,我在初始化路线之前解析了HTTP来电:

@Injectable()
export class DataResolve implements Resolve {

  constructor(private service: DataService, private router: Router) {}

  resolve(route: ActivatedRouteSnapshot):
    Observable<any> | Promise<any> | any {
      return this.service.getData().then(data => {
        if (data) {
          return data;
        } else {
          this.router.navigate(['/page/1']);
         return false;
       }
    });
  }
}

然后,我需要将该服务添加到我的模块提供商:

providers: [DataService, DataResolve]

并且在加载路线之前告诉路由解决这个问题:

resolve: { pages: DataResolve }

之后,我将在我的组件中使用一个数组来获取数据:

this.route.data.forEach((data: {pages}) => {
  this.data = data.pages;
});

我还用一个工作示例更新了我的Plunker