私のシナリオは次のとおりです。複数のオプションがあるメニューがあります。各メニューはユーザー権限に応じて表示され(既に解決済み)、ほとんどのメニュー項目はモジュールとしてカプセル化され、ほとんどのモジュールは遅延ロードされるため、ユーザーが初めてメニュー項目をクリックするとロードされます(ここまですべて)うまくいきます)、私の要件は、より良いユーザーエクスペリエンスを提供するために、遅延ロードされたモジュールがロードされている間にユーザーがメニューアイテムをクリックした後にアクティビティインジケーターを表示する必要があることです。
これまで、Angular Routerから運が良かったので、canActive、canLoad、canActivateChildインターフェイスを使用してみました。
何か案は?
次の2つのルーターイベントをリッスンできます。
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でこのアプローチを使用しています
このようにできます
<div class="main-loader" *ngIf="loading"> <div class="cssload-container" > <div class="cssload-whirlpool"></div> </div> </div>
app.component.ts内
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
});
}
cSSで読み込みアニメーション
これがあなたの役に立つことを願っています。ありがとう
最初のロード中に、他の遅延ロードされたルートへのリンクをクリックすることができます。そのため、ロードされているルートをカウントする必要があります。
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>
CSSを使用できます!
<routler-outlet></routler-outlet>
<div class='.loader>
Just, wait a sec ! I'm loading
</div>
テンプレートで
router-outlet + .loader {
opacity : 1;
}
.loader {
opacity : 0;
}
次に、 HTML/CSSの派手なスピナー を作成できます
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);
}