Vue.Jsのv-forディレクティブはforEachと考えればしっくりくる!


この記事について

JavaScriptもろくに書けないにも関わらずいきなり、Vueをバリバリ使った案件にぶち込まれて、はや半年。最初に理解に苦しんだのが"v-for"。
今ではv-forにはかなりお世話になっているが、最初のうちはもの凄く苦しんだ。
何せfor文すら書けなかったのだから無理もない。

そもそもv-for とは??

まずVue.jsを触りはじめたときは、ディレクティブすら意味が分からなかった。
よくもまあそんな状態で初めたものである。

簡単にいうとディレティブとは、Html側でJavaScriptっぽいことができるように、
Vue.Jsで用意されている便利な部品のこと だと私は思っている。
Vueにはいろんなディレクティブが用意されている。それらを駆使することによって、
ScriptからHtmlへのアクセス(逆もしかり)が非常に簡単になるというのがVue.Jsの
本質かと思う。

それではv-for は何かというと
公式サイトによると

v-for で配列に要素をマッピングする
配列に基づいて、アイテムのリストを描画するために、v-for ディレクティブを使用することができます。v-for ディレクティブは item in items の形式で特別な構文を要求し、items はソースデータの配列で、item は配列要素がその上で反復されているエイリアスです:

半年前のど素人の私なら、完結に書かれすぎてさっぱり分からなかった。
今見返すと実に完結に書かれてある。(笑)
当然、初学者にはわかるはずもない(笑)私だけだったりして

私なりの見解だが、ある配列の値を表示するために、v-forというVueが用意した
便利な部品を使って、item in itemsみたいな書き方でその値を取得して、itemで反復して配列を呼び出すことができるというのがv-forだ。
自分で書いていてもよくわからなくなってきたので、JavaScriptのforEachを考えればしっくりくるのではないか?

試しにforEachを使って配列の値をconsole.logで表示させるコードを下記に示したい。
items という配列をitemという引数を使って、一つずつ描画していることがわかる。
Vue.jsではv-forを使うことで、いちいちforEachなんて書かなくて済むのだ。

JavaScript
const items = ['item1', 'item2', 'item3']
const copyItemsArray = []
items.forEach((item) => {
  copyItemsArray.push(item)
 console.log(item)
})
//結果は
//item1
//item2
//item3
//と表示される。

もう少しforEachにお付き合いいただきたい。
今度は連想配列で考えてみる。

JavaScript
const objectItems = [
  {name:"太郎",age:22},
  {name:"治郎",age:20},
  {name:"三郎",age:18}
]
const objectArray = []
objectItems.forEach((item)=>{
  objectArray.push(item)
  console.log(`名前:${item.name}/年齢:${item.age}`)
})
//名前:太郎/年齢:22
//名前:治郎/年齢:20
//名前:三郎/年齢:18

forEachを知って、かなりしっくりきた。
というかv-forもforEachもかわらんやん(笑)

さて、ここで、v-for を使用して描画とやらをやってみる。
CSSは苦手なので、Vuetifyを使用している。
それと普段のプロジェクトで、TypeScriptを触っている都合上
私が一番慣れている書き方で書かせていただいた。

Vue.js
<template>
    <div>
        <ul>
            <li v-for="(brother,i) in brothers" :key="i">名前{{brother.name}}/年齢:{{brother.age}}</li>
        </ul>
    </div>
</template>
<script lang="ts">
import { Component, Vue } from 'nuxt-property-decorator'

interface Person {
    name:string
    age:number
}
@Component({})
export default class extends Vue{
    brothers:Person[] = [
        {name:"太郎",age:22},
        {name:"治郎",age:20},
        {name:"三郎",age:18}
    ]
}
</script>

↑こんな感じで描画される。
v-forを使用するときは、注意点としてkey要素というものをつけなければならない。
大抵の場合はオブジェクトの中にidなんかがあってそれをkey要素として返してあげるのだが、とくにid指定がないときなんかはindexで返してあげるのがベター。
その場合は、v-forのitemの2番目の引数としてindexを取ることができるので、
(item,i)のように書いてあげる。
このv-for のkeyの動作については下記のサイトに非常に詳しく載っているのでぜひ参考にしてみてほしい。
参考: 【徹底解説】これを見ればわかるvue.jsのv-forのkeyの動作

さて、せっかくUI frameworkとしてVuetify.jsを使用しているのだから、
何かコンポーネントを使用して描画してみよう。
今回はv-simple-tableというコンポーネントを使用。
その名の通り、めっちゃシンプルなコンポーネント。

Vue.js
<template>
    <div>
        <ul>
            <li v-for="(brother,i) in brothers" :key="i">名前{{brother.name}}/年齢:{{brother.age}}</li>
        </ul>
        <v-simple-table>
            <template v-slot:default>
                <thead>
                    <tr>
                        <th>名前</th>
                        <th>年齢</th>
                    </tr>
                </thead>
                <tbody>
                    <tr
                        v-for="(brother,i) in brothers" :key="i">
                        <td>{{brother.name}}</td>
                        <td>{{brother.age}}</td>    
                    </tr>
                </tbody>
            </template>
        </v-simple-table>
    </div>
</template>
<script lang="ts">
import { Component, Vue } from 'nuxt-property-decorator'

interface Person {
    name:string
    age:number
}
@Component({})
export default class extends Vue{
    brothers:Person[] = [
        {name:"太郎",age:22},
        {name:"治郎",age:20},
        {name:"三郎",age:18}
    ]
}
</script>

↑こんな感じで描画される。

v-forなんて簡単

Vue.Jsなんて所詮はJavaScriptのフレームワーク(笑)って言ってみたかったのだが、
半年前の自分にいってやりたい。
まだまだひよっこエンジニアの私だが、最初は公式ページを見てもちんぷんかんぷん。
何度辞めたいと思ったことか、、、、、、

Vue.Jsは慣れれば非常に便利なツールだと思っている。
なんなら私なんて、innerHTML とか書けない(笑)
恥ずかしくて言えないが、、、、、
それはいいか悪いのか別として、非常に楽なツールである。
最初、Vueの勉強を始めたときは、”学習コストが低いのがVue。だから、初心者向きなんだ”って書いていたサイトを見て、俺は全く理解できていないから、もう辞めた方がいいのか、、、なんて本気で悩んだこともある。

勉強する順序が悪かっただけだった。
これからもVue.Jsを使ってガンガン開発に挑戦してみようと思っている。

最後まで読んでくださった方ありがとうございました。