[解決済み] Angular 2 でルート間を移動するときにローディング画面を表示する
2022-07-09 19:28:51
質問
Angular 2でルートを変更するときにローディング画面を表示するにはどうしたらよいですか?
どのように解決するのですか?
現在のAngular RouterはNavigation Eventsを提供しています。これらを購読し、それに応じてUIを変更することができます。他のEventもカウントすることを忘れないでください。
NavigationCancel
と
NavigationError
で、ルータの遷移に失敗した場合にスピナを停止させることができます。
app.component.ts - あなたのルートコンポーネント
...
import {
Router,
// import as RouterEvent to avoid confusion with the DOM Event
Event as RouterEvent,
NavigationStart,
NavigationEnd,
NavigationCancel,
NavigationError
} from '@angular/router'
@Component({})
export class AppComponent {
// Sets initial value to true to show loading spinner on first load
loading = true
constructor(private router: Router) {
this.router.events.subscribe((e : RouterEvent) => {
this.navigationInterceptor(e);
})
}
// Shows and hides the loading spinner during RouterEvent changes
navigationInterceptor(event: RouterEvent): void {
if (event instanceof NavigationStart) {
this.loading = true
}
if (event instanceof NavigationEnd) {
this.loading = false
}
// Set loading state to false in both of the below events to hide the spinner in case a request fails
if (event instanceof NavigationCancel) {
this.loading = false
}
if (event instanceof NavigationError) {
this.loading = false
}
}
}
app.component.html - あなたのルートビュー
<div class="loading-overlay" *ngIf="loading">
<!-- show something fancy here, here with Angular 2 Material's loading bar or circle -->
<md-progress-bar mode="indeterminate"></md-progress-bar>
</div>
パフォーマンス向上への回答
: もしあなたがパフォーマンスを気にするなら、より良い方法があります。それは実装が少し面倒ですが、パフォーマンスの向上は余分な作業に値するでしょう。代わりに
*ngIf
を使って条件付きでスピナーを表示する代わりに、Angular の
NgZone
と
Renderer
でスピナーのオン・オフを切り替えると、スピナーの状態を変更したときにAngularの変更検出をバイパスすることができます。私は、この方法が
*ngIf
や
async
というパイプがあります。
これは前回の回答に似ていますが、少し手を加えています。
app.component.ts - あなたのルートコンポーネント
...
import {
Router,
// import as RouterEvent to avoid confusion with the DOM Event
Event as RouterEvent,
NavigationStart,
NavigationEnd,
NavigationCancel,
NavigationError
} from '@angular/router'
import {NgZone, Renderer, ElementRef, ViewChild} from '@angular/core'
@Component({})
export class AppComponent {
// Instead of holding a boolean value for whether the spinner
// should show or not, we store a reference to the spinner element,
// see template snippet below this script
@ViewChild('spinnerElement')
spinnerElement: ElementRef
constructor(private router: Router,
private ngZone: NgZone,
private renderer: Renderer) {
router.events.subscribe(this._navigationInterceptor)
}
// Shows and hides the loading spinner during RouterEvent changes
private _navigationInterceptor(event: RouterEvent): void {
if (event instanceof NavigationStart) {
// We wanna run this function outside of Angular's zone to
// bypass change detection
this.ngZone.runOutsideAngular(() => {
// For simplicity we are going to turn opacity on / off
// you could add/remove a class for more advanced styling
// and enter/leave animation of the spinner
this.renderer.setElementStyle(
this.spinnerElement.nativeElement,
'opacity',
'1'
)
})
}
if (event instanceof NavigationEnd) {
this._hideSpinner()
}
// Set loading state to false in both of the below events to
// hide the spinner in case a request fails
if (event instanceof NavigationCancel) {
this._hideSpinner()
}
if (event instanceof NavigationError) {
this._hideSpinner()
}
}
private _hideSpinner(): void {
// We wanna run this function outside of Angular's zone to
// bypass change detection,
this.ngZone.runOutsideAngular(() => {
// For simplicity we are going to turn opacity on / off
// you could add/remove a class for more advanced styling
// and enter/leave animation of the spinner
this.renderer.setElementStyle(
this.spinnerElement.nativeElement,
'opacity',
'0'
)
})
}
}
app.component.html - あなたのルートビュー
<div class="loading-overlay" #spinnerElement style="opacity: 0;">
<!-- md-spinner is short for <md-progress-circle mode="indeterminate"></md-progress-circle> -->
<md-spinner></md-spinner>
</div>
関連
-
[解決済み] JavaScriptで要素のクラスを変更するにはどうすればよいですか?
-
[解決済み] リンクのように動作するHTMLボタンを作成する方法
-
[解決済み] HTML 5: Is it <br>, <br/>, or <br />?
-
[解決済み] リスト項目にマウスを置いたときに、カーソルを手の形に変えるには?
-
[解決済み] div' コンテナに合わせて画像を自動リサイズするにはどうしたらいいですか?
-
[解決済み] ngModel' は 'input' の既知のプロパティではないため、バインドできません。
-
[解決済み] CSSコンテンツによるHTMLエンティティの追加
-
[解決済み] Angular/RxJS `Subscription` からいつ退会すればいいのか?
-
[解決済み] 現在のルートを取得する方法
-
[解決済み】jQueryでチェックボックスがチェックされているかどうかを確認するにはどうすればよいですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] Bootstrap 3.3.7で改行する方法
-
[解決済み] HTMLのテーブルからボーダーを完全に削除する方法
-
[解決済み] input type="button "に背景画像を追加するには?
-
[解決済み] 要素を水平方向にセンタリングする方法
-
[解決済み] CSSでテキストや画像の背景を透明にするには?
-
[解決済み] divブロック内のテキストを(水平方向と垂直方向に)センタリングするにはどうすればよいですか?
-
[解決済み] 入力テキストボックスの値を取得する
-
[解決済み] Flexbox:水平方向と垂直方向の中央揃え
-
[解決済み] CSS 背景の不透明度 [重複]について
-
[解決済み] HTML5で(非空白の)自己閉鎖タグは有効ですか?