AngularJSを使ったWebアプリケーションで、ページの読込途中や初期化までの間にテンプレートのマークアップ(下記の図の{{name}}のような記述)が一瞬見えてしまうのを何とかしたい時があります。
特にページの表示開始を早くするためにAngularJSのコード読み込みをhead要素に置かずに非同期で読み込んでいる場合は、AngularJSの読み込み完了まで見えてしまうので特に目立ってしまいます。これを解決するためにngCloakというdirectiveがあるのでこれを使います。(headセクションでAngularJSのコード読み込みのscriptタグを配置している場合はそんなに気にならないかもしれません。公式ドキュメントではこの方法を推奨しているようです)
使い方
連携するCSSをアプリケーションのCSSに追加します
[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {
display: none !important;
}
隠したい要素の属性にng-cloakを付けます
<div id="content" ng-cloak>
<h1>{{hogehoge}}</h1>
...
</div>
これだけです。
ng-cloakはbodyに付けると一箇所だけで済むので楽が出来ますが、プログレッシブレンダリングを可能にしてユーザにストレスを与えないようにするためにも、影響のある場所にのみ複数に分けて設定するほうが好ましいようです。また、IE7などの属性セレクタをサポートしないレガシーブラウザに対応したい場合は上記のディレクティブのみでは不足するため、class="ng-cloak"
を追加して以下のようにすると良いようです。
<div id="content" class="ng-cloak" ng-cloak>
<h1>{{hogehoge}}</h1>
...
</div>
動作の比較
ng-cloakの有無による違いを確かめるためのサンプルページはこちらです。サンプルとして3つのページを用意しています。これらはHello, world!を表示するサンプルとなっており、それぞれ以下のことを行っています。
- 変数nameにworldをセット
- $httpで非同期に取得したjsonを使って変数nameを上書き(設定されたのを分かりやすくするために上書きを500ms遅らせています)
また、3つのページの違いは以下の通りです。
no | 名称 | ng-cloak有無 | angular.js読込方法 |
---|---|---|---|
1 | ng-cloak | 有 | 500ms遅延非同期 |
2 | no-ng-cloak(async) | 無 | 500ms遅延非同期 |
3 | no-ng-cloak(sync) | 無 | 遅延なし同期 |
非同期のngCloak無しバージョンではマークアップが見えてしまっているのが確認できます。また、AngularJSの同期と非同期では、AngularJSの読み込み完了前にページがレンダリングされるか、読み込み完了後にレンダリングされるかの違いが確認できます。
サンプルコード
上記のサンプルコードはこちらにあります。