この記事をおすすめしたい人
- Nuxt3でv-forとv-ifの併用ができなくて困っている人
- Nuxt3でv-forとv-ifの併用の代案を探している人
- つまりオレ
Nuxt v3の調査、v-forとv-ifの併用編です。
v2でもv-forとv-ifの併用には注意が必要って確か公式が書いてたんですが忘れました。 v3では非推奨とかのレベルじゃなくて、完全にできなくなっています。
その辺の事情と、できなくなったことへの対策を3つ考えましたよ。
やろうとしていること
例えばこんな↓オブジェクトの配列があるとして、
{
id: 1,
name: '名前①',
show: true,
}
v-forを使ってこんな↓風に列挙するとします。
<ul>
<li v-for="row in list">{{row.id}}: {{row.name}}</li>
</ul>
さらに、各データの「show」の部分をフラグとして、trueなら表示、falseなら非表示にしようとするとこんな↓コードになります。
<ul>
<li v-for="row in list" v-if="row.show">{{row.id}}: {{row.name}}</li>
</ul>
けっこうよくある処理だと思うんですよね。
ですがv2の時もこのようなv-forとv-ifの併用はよくないよ、○○○なケース以外では使わないでね、とVue公式が書いてた気がします。 ○○○なケースというのが上のような例だった気がしたんですが忘れました。 記事にもした気がするのに見当たりません。
でもv2では実際に動いていたコードです。
これがNuxt3で出来なくなりました。 推奨しないんではなくて物理的にできません。
公式の説明によると、v-ifの方が先に参照されるらしく、その段階でv-forの方の各行のデータが存在してないからみたいです。 上の例だとrowが宣言される前に呼び出されますよーみたいなエラーが出ます。
対策① templateタグを使う
公式が代替案として推奨している方法です。
<ul>
<template v-for="row in list">
<li v-if="row.show">{{row.id}}: {{row.name}}</li>
</template>
</ul>
liの外側をtemplateで囲う方法です。
これだと同じタグでのv-forとv-ifの併用がなくなり、内側のliではrowを参照できるようになるわけです。
対策② filterを使う
そもそもshowをフラグとして条件分岐することが分かっているなら、こんな↓風に先にfilterでtrueのものだけ抽出してしまうのも手だと思います。
<ul>
<li v-for="row in list.filter(r => r.show)">{{row.id}}: {{row.name}}</li>
</ul>
でもHTML部分でコードを書くのがあまり好きじゃないのでなんかビミョー。
対策③ コンポーネントを使う
こんな↓風にliの部分をコンポーネントにしてしまう方法もありますね。
<ul>
<MyComponent v-for="row in list" :row="row" />
</ul>
独自コンポーネントでv-forする時はkeyが必要↓なので注意
<ul>
<MyComponent v-for="row in list" :key="row.id" :row="row" />
</ul>
で、コンポーネント内↓でv-ifを使う。
<template>
<li v-if="row.show">{{row.id}}: {{row.name}}</li>
</template>
嫌いではないですが、1箇所でしか使わない小規模な処理でコンポーネントは増やしたくないな。 いつも10~20くらいはできてしまうので。
まとめ
v-forとv-ifを併用できなくなった問題を解決する方法を3つ紹介しました。
個人的には公式が推奨してるtemplateを使う方法が書き換え箇所も少なくてスマートかなーと思いました。
以上、WordPressからお届けしました!
Nuxt.js v3の目次
- 第1回 インストール方法とかフォルダ構成の違いとか
- 第2回 nuxt.config.jsの書き方の違い
- 第3回 注意が必要そうなモジュール
- 第4回 コンポーネントのscriptの書き方がめっちゃ変わった
- 第5回 trailingSlashに手動で対応
- 第6回 injectの代用品を3つ紹介
- 第7回 v-forとv-ifの併用の代替案(このページ)
- 第8回 defineNuxtComponentは救世主!
- 第9回 composablesがめっちゃ強いかもしれない
- 第10回 手動でAMPに対応する
- 第11回 フック一覧を簡単に調べた
- 第12回 axiosの代用品(useFetch、$fetch、useAsyncData)