bind前にViewが見えてしまう問題への解決方法


Knockout.jsにしろ、それ以外のJavaScriptのMVVMにしろ、bind前にViewがチラッと見えてしまうことがありますね。あれをなんとかしたいなーと思っていたので、その解決方法についてです。

アプローチ1: ViewModelがbindされるまで隠す(View単位)

.ko-hiddenというcssのクラスを作って、隠してしまう作戦です。

.ko-hidden {
  display: none;
}

これを、該当するViewに当てておきます。

.ko-hidden data-bind="with: fooViewModel"

これに対して、bindingし終えたら表示するというものです。

window.load ->
  ko.applyBindings(app_view_model)
  $('.ko-hidden').removeClass('ko-hidden')

上記の方法だと、いきなりバッと表示されてしまうので、フェードインで表示したい場合は、こう。

window.load ->
  ko.applyBindings(app_view_model)
  $('.ko-hidden').fadeIn().removeClass('ko-hidden')

アプローチ2: ViewModelがbindされるまで隠す(全体)

bindingが終わるまで、body自体を非表示にするという方法。

cssは同じ。

.ko-hidden {
  display: none;
}

これをbodyタグにあてます。

body.ko-hidden

そして、bindingし終えたら表示。

window.load ->
  ko.applyBindings(app_view_model)
  $('body').removeClass('ko-hidden')

それぞれのメリットとデメリットについて

View単位

メリット

  1. 対象のView以外は表示されるため、体感速度的には速いんじゃないだろうか
  2. SEO的な問題が発生しない
  3. あとからでも導入しやすい

デメリット

  1. 全ての一時的に非表示にしたいViewに対して作業を行う必要がある。

全体

メリット

  1. 1回の作業でいい

デメリット

  1. 体感速度的に遅いと感じるかもしれない
  2. SEO的な問題が発生しうる(最初真っ白だから)
  3. 要素の大きさを計算したりするようなJSを組んでいると、初期表示で要素が非表示のため、計算がうまくいかない。そのため、あとから導入しづらい。

まとめ

簡単なのは全体を隠すほうだけれど、複雑な条件に対応できるのはView単位に対応するほうかなと思う。
私はView単位で対応する方法をとった。