在Angular 2中加载延迟加载的模块时显示活动指示器

时间:2017-03-23 15:59:16

标签: angular lazy-loading angular2-routing

我的方案如下。我有一个菜单,有多个选项。应该根据用户权限(已经解决)显示每个菜单,大多数菜单项都封装为模块,并且大多数模块都是延迟加载的,因此当用户第一次单击菜单项时,它会加载(到此为止所有内容)效果很好),现在我的要求是,为了提供更好的用户体验,我需要在加载延迟加载的模块时用户点击菜单项后显示活动指示器。

到目前为止,我尝试使用canActive,canLoad,来自Angular Router的canActivateChild接口,但没有运气。

有什么想法吗?

5 个答案:

答案 0 :(得分:51)

您可以收听两个路由器事件:

  • RouteConfigLoadStart
  • RouteConfigLoadEnd

它们在加载延迟加载的模块时触发。在标准路由器事件(例如NavigationStart)上使用这些事件的好处是,它们不会在每次路由更改时触发。

在您的根AppComponent中收听它们以显示/隐藏您的微调器。

<强> app.component.ts

import { Router, RouteConfigLoadStart, RouteConfigLoadEnd } from '@angular/router';

...

export class AppComponent implements OnInit {

    loadingRouteConfig: boolean;

    constructor (private router: Router) {}

    ngOnInit () {
        this.router.events.subscribe(event => {
            if (event instanceof RouteConfigLoadStart) {
                this.loadingRouteConfig = true;
            } else if (event instanceof RouteConfigLoadEnd) {
                this.loadingRouteConfig = false;
            }
        });
    }
}

<强> app.component.html

这里只是一个简单的字符串,但您可以使用微调器组件。

<router-outlet></router-outlet>

<ng-container *ngIf="loadingRouteConfig">Loading route config...</ng-container>

我在Angular v4.2.3中使用这种方法

答案 1 :(得分:23)

你可以这样做

  1. 在app.component.html
  2. <div class="main-loader" *ngIf="loading">
      <div class="cssload-container" >
          <div class="cssload-whirlpool"></div>
      </div>
    </div>
    
      app.component.ts中的
    1. import { Router, NavigationStart, NavigationEnd } from '@angular/router';
      
      
      loading:boolean = false;
      constructor(private router:Router) { 
        router.events.subscribe(event => {
          if(event instanceof NavigationStart) {
            this.loading = true;
            console.log("event started")
          }else if(event instanceof NavigationEnd) {
            this.loading = false;
            console.log("event end")
          }
          // NavigationEnd
          // NavigationCancel
          // NavigationError
          // RoutesRecognized
        });
      
      }
      
    2. 在css任何加载动画

    3. 希望这对你有用。感谢

答案 2 :(得分:1)

在加载第一个路径时,可以单击指向其他延迟加载路径的链接。这就是为什么我们需要计算正在加载的路线:

<强> app.component.ts

```

export class AppComponent { 

  currentlyLoadingCount = this._router.events.scan((c, e) => this._countLoads(c, e), 0);

  constructor(private _router: Router) { }

  private _countLoads(counter: number, event: any): number {
    if (event instanceof RouteConfigLoadStart) return counter + 1;
    if (event instanceof RouteConfigLoadEnd) return counter - 1;
    return counter;
  }

```

<强> app.component.html <ng-container *ngIf="currentlyLoadingCount | async">Loading route config...</ng-container>

答案 3 :(得分:0)

你可以使用CSS!

<routler-outlet></routler-outlet>
<div class='.loader>
  Just, wait a sec ! I'm loading
</div>

在您的模板中

router-outlet + .loader {
  opacity : 1;
}

.loader {
  opacity : 0;
}

然后您可以创建fancy spinners with HTML/CSS

答案 4 :(得分:0)

对于那些需要与IE11兼容(和处理)的人来说,接受的答案是行不通的,因为IE11在从一个模块切换到另一个模块时不会渲染加载器,所以我做了一个(不是很优雅但是工作正常)解决方法:

在我的menuItem开关中单击事件:

  public navigate(url: string) {
    this.configurationService.loading = true; //service variable linked with html loader

    //let's give time to tortoise IE11 to render loader before navigation...
    let obj = this;
    setTimeout(function() 
    {
      obj.router.navigateByUrl(url);
    }, 1);
  }