背景
Vue.jsのチラつきとは
Vue.jsの「マスタッシュ表記({{ data }}のような表記)」や「v-if」などで表示を制御している場合、ページ読み込み直後に一瞬だけVueデータが反映される前のコードが表示されてしまうことがある。これを経験した人は少なくないと思う。
v-cloakでの対策と問題点
このチラつきの解決策をネットで検索すると、「v-cloakを使いましょう」という記事が出てきて、下記のようなサンプルコードを提案される。
index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<style type="text/css">
[v-cloak] {
display: none;
}
</style>
</head>
<body>
<div id="app" v-cloak>
<p>{{ message }}</p>
</div>
<script type="text/javascript">
new Vue({
el: '#app',
data: {
message: "メッセージ",
},
});
</script>
</body>
</html>
ただの html や php 環境ならこの方法で解決できる。しかし、Laravel の blade で Vue.js を使用している場合、この方法では解決しないことがある。
(条件や原因を特定できていないので、もし知っている人はコメントいただけるとありがたいです。)
v-cloakを使わない解決方法
サンプルコード
v-cloakと同様の処理を下記サンプルコードのように自作してしまえば解決できる。
index.blade.php
<!DOCTYPE html>
<html lang="ja">
<head>
</head>
<body>
<div id="app" style="display:none"><!-- (1)html読み込み時はcssで非表示 -->
<p>@{{ message }}</p>
</div>
<script type="text/javascript">
new Vue({
el: '#app',
data: {
message: "メッセージ",
},
mounted: function () {
const targetElement = this.$el;
this.$el.style.display='block'; // (2)vueマウント完了後に表示させる
},
});
</script>
</body>
</html>
解説
- まず、Vueの制御対象のコンテンツ全体を「style="display:none"」で非表示にしておく。こうすることで、Vueと連動する部分はページ読み込み直後であっても表示されない。
- Vueインスタンスが生成され、エレメントのマウントが完了後(=Vueインスタンスのデータがhtmlコード側に反映された後)に、非表示を解除する。
同様の問題で困っている人の参考になれば幸いです。