はじめに
Vue.jsスタイルガイドによると、v-if
と v-for
を一緒に使うのは避けるべきとされています。
一緒に使うというのは
<template v-for="item in items" v-if="item.key === 1" :key="item.id">
<li>
<router-link :to="item.url">{{ item.pages }}</router-link>
</li>
</template>
上記のような、同一のタグの中にv-forとv-ifを詰め込んでいる状態のことを指しています
とある記事のコメントにてv-forとv-ifの併用を勧めてしまって、(もちろん訂正コメントも送信しています)
今後同じことを勧めないようにアウトプットで書きました。
なぜだめなのか
Vue がディレクティブを処理するとき、v-forは v-if よりも優先度が高いとされていて
上の例の中身の処理をJavaScriptで書くと
this.items.map(function (item) {
if (item.key === 1) {
return item.url
}
})
このようになります
これだとresultに変更があった際に実際に表示されるitemの変更の有無にかかわらず
再度繰り返し処理されるのです
じゃあどうしたいいんか
実際に表示されるitemに変化があったり条件に合うitemが増減したりする際にのみ
繰り返し処理を行うようにします。
<ul>
<li v-for="item in resultKey">
<router-link :to="item.url">{{ item.pages }}</router-link>
</li>
</ul>
~~~省略
computed: {
resultKey: function () {
return this.items.filter(function (item) {
return item.key === 1
}
})
}
}
今回は算出プロパティを使って解決しました。
こうすることで以下の利点が得られます
フィルタリングされたリストは items 配列に関連する変更があった場合に のみ 再評価されるので、フィルタリングがはるかに効率的になります。
v-for="item in activeUsers" を使用して、描画中にkeyが1のitem のみ 繰り返し処理するので、描画がはるかに効率的になります。
ロジックがプレゼンテーションレイヤから切り離され、メンテナンス(ロジックの変更/拡張)がはるかに容易になります。
(参照: Vue.js スタイルガイド v-for-と一緒に-v-if-を使うのを避ける-必須)
おわり
Vue.jsって結構なんでもできちゃうのでおっこれでいけるじゃん!と思っていたものは実は推奨されていない書き方って結構あるかもですね(ドキュメントしっかり読んでいるからそんなことないわって思っている方もいるかもですが)
つまりドキュメント最強です
これ大丈夫なのかって思ったらとりあえずドキュメントですね