【Vue Router】APIデータを配列型でcomponentに渡して展開させたい

SPAでサイトを構築する際に、APIのデータが入ったファイルから同一componentへ、同一の項目を渡したいというシチュエーションでは以下のような方法が役に立ちます。

具体的なシチュエーション

商品ページをSPAで作る際に、商品名や値段などは各商品1つでいいけれど、写真は複数枚送りたい。
だけど 、以下のように各項目に1つしか入れる方法が見つからない…

const url = [
    {id: 1, url: '/static/images/invoice.png'}
    ]

const database = [
    {
        id : 1,
        name : "Invoice'n to do",
        url :  'https://invoice-andtodo.herokuapp.com/',
        content : '請求書と仕事管理が同時にできるアプリです。' ,
        photo :  url,
    },

解決策

以下にAPIデータが格納されているファイルと、商品ページコンポーネントとなるファイルのコードを記述します。

src/api/products.js

const url = [
    {id: 1, url: '/static/images/invoice.png'},
    {id: 2, url: '/static/images/invoice.png'},
    ]

const database = [
    {
        id : 1,
        name : "Invoice'n to do",
        url :  'https://invoice-andtodo.herokuapp.com/',
        content : '請求書と仕事管理が同時にできるアプリです。' ,
        photo :  url,
    },
    {
        id : 2,
        name : "App Order Made",
        url : 'http://order-made-matching.herokuapp.com/',
        content : 'オーダーメイドアプリを作ってほしい人と安価でいいのでアプリ作りを請け負いたいエンジニアのマッチングサイトです。' ,
        photo : url,
    },
    {
        id : 3,
        name : "Old Book Store",
        url : 'https://old-book-store04.herokuapp.com',
        content : '我が家にある古本を売っています。' ,
        photo : url,
    },
    {
        id : 4,
        name : "ShareHouse Australia",
        url : 'https://sharehouse-australia.herokuapp.com',
        content : 'オーストラリアのシェアハウスを位置情報から探せるサイトです。' ,
        photo : url,
    },
    
    ]
    
export default {
    fetch(id) { return database },
    find(id) { return database.find(el => el.id === id) },
    asyncFind(id, callback) {
        setTimeout(() => {
            callback(database.find(el => el.id === id), 1000)
        })
    }
}

src/views/Product.vue

<template>
    <div class="product" v-if='item' key='product'>
        <h1>{{ item.name }}</h1>
        <h1>{{ item.url }}</h1>
        <h1>{{ item.content }}</h1>
        <span v-for=' img in item.photo '>
            <img :src="img.url" v-if="img.id === item.id  "/>
        </span>
    </div>
    <div v-else key='loading'>Loading...</div>
</template>

<script>
import products from '@/api/products.js'
export default {
    props: { id: Number },
    data() {
        return {
            item : null
        }
    },
    watch: {
        id: {
            handler() {
                products.asyncFind(this.id, item => {
                    this.item = item
                })
            }, immediate: true
        }    
    }
}
</script> 

解説

APIのデータが入るproduct.jsからcomponentであるproduct.vueの方へ、渡したい配列を変数に格納して全て送ります。

その後、APIデータを展開する中で、photoだけは配列型でリストレンダリングされているので、さらにv-forで展開。そして、v-ifを使用してidによって表示・非表示を切り分けます。

v-showでも良さそうですね。
v-ifとv-showの違いはこちらの記事で。


v-ifで振り分けるためにidを使っていますが、これはSPAで映し出される各商品のidに合わせています。そのため変数urlを打ち込むのは手作業にて悪しからず。