Works by

Ren's blog

@rennnosuke_rk 技術ブログです

【AngularJS】未コンパイル状態のHTMLテンプレートが一瞬表示されるのを防ぐ

テンプレートのちらつき

AngularJSのHTMLテンプレートを用いたページを表示したときに、一瞬だけ元のテンプレート表記がちらついてしまう場合があります。

例えば、以下のようなコードでHTML上の{{message}}に動的に文字列を挿入しようとしたとき、下の画像のように一瞬だけ元の文字列{{message}}の状態で表示されてしまうことがあります。

<div ng-app="myApp">
  <div ng-controller="MyAppCtrl">
    {{message}}
  </div>
</div>
let mod = angular.module('myApp',[]);
mod.controller('MyAppCtrl', ['$scope', '$timeout', function($scope, $timeout){
    $scope.message = "Hello!";  
}]);
結果

f:id:rennnosukesann:20180509221001p:plain

ng-cloak

このチラツキを防ぐために、ng-cloakディレクティブを使用します。
このディレクティブを指定したタグは、テンプレートにデータが挿入されるまで非表示状態になります。テンプレートにデータが挿入されたときタグは表示状態となり、未コンパイル状態のテンプレートが露出されずに済みます。

<div ng-app="myApp">
  <div ng-controller="MyAppCtrl" ng-cloak>
    {{message}}
  </div>
</div>
結果

f:id:rennnosukesann:20180509222125p:plain

内部では、画面読み込み時にng-cloakを指定したタグに対して下記のCSSルールが適用されています。そしてng-cloakディレクティブを指定したタグの内側に含むテンプレートがコンパイルされるとき、AngularJSはng-cloak属性を破棄します。

[ng:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {
  display: none !important;
}

この一連の操作によって、「テンプレートにデータが挿入されるまでタグを表示しない」処理を実現しています。

なおng-cloakは指定したタグの子要素もすべて非表示にしてしまいます。そのため<body ng-cloak>とするなど、指定の仕方によってはページの表示が遅延しているように見えてしまうため、ユーザ体験を悪化させる要因になりかねません。

ちらつく可能性のあるテンプレートが特定の領域に限られている場合には、その領域のタグに限定してng-cloakを付加するのが望ましいです。

参考文献

ngCloak | AngularJS 1.2 日本語リファレンス | js STUDIO