Nuxt.jsとvue-magic-gridというライブラリを使ってフォトギャラリーっぽいものを作ってみます。

環境


下記の環境で試してます。

  • nuxt: 2.8.1
  • @nuxtjs/axios: 5.5.4
  • vue-magic-grid: 0.0.4

出来上がり


出来上がりは下記のようなものを目指します。実際に動くものはここにあります

インストール


今回は@nuxtjs/axiosvue-magic-gridをつかうのでそれらをインストールします。ただし、データを分離せずにビューに直接記述するのであれば@nuxtjs/axiosは不要です。

1
$ npm install vue-magic-grid @nuxtjs/axios

axiosの設定


@nuxtjs/axiosの使い方は基本的に公式ドキュメントのとおりで、後は一つ前の記事で書いた通りに開発と本番で取得先のURLが変わるように設定します。

Pluginsで呼び出す


Nuxt.jsでVueのプラグインを使うにはpluginsディレクトリで対象となるプラグインをVue.useすればよいです。なので、magic-grid.jsというファイルを作って下記のようなコードを書きます。

1
import Vue from "vue";
2
import MagicGrid from "vue-magic-grid";
3
4
Vue.use(MagicGrid);

これをnuxt.config.jsで指定します。

1
export default {
2
  ...
3
  plugins: [
4
    "~/plugins/magic-grid"
5
  ],
6
  ...
7
}

コンポーネントを作る


次に写真付きカード表示用するコンポーネントを作ります。下記のようなコードを書いてcomponents/Card.vueとかそんな感じの名前で保存します。

1
<template>
2
  <div class="card large">
3
    <div class="card-image">
4
      <figure class="image">
5
        <img v-bind:src="image" alt="Image" />
6
      </figure>
7
    </div>
8
    <div class="card-content content">
9
      <h6>{{ title }}</h6>
10
      <p>{{ body }}</p>
11
    </div>
12
  </div>
13
</template>
14
15
<script>
16
export default {
17
  name: "card",
18
  props: {
19
    image: {
20
      type: String,
21
      default: ""
22
    },
23
    title: {
24
      type: String,
25
      default: ""
26
    },
27
    body: {
28
      type: String,
29
      default: ""
30
    }
31
  }
32
};
33
</script>

データを準備する


次にカードに表示するデータのjsonを用意します。これをstatic/dataの下らへんにimages.jsonとかなんかそんな感じで保存します。

1
[
2
  {
3
    "image": "https://example.com/images/1.jpg",
4
    "title": "Test One",
5
    "body": "Description One"
6
  },
7
  {
8
    "image": "https://example.com/images/2.jpg",
9
    "title": "Test Two",
10
    "body": "Description Two"
11
  },
12
  {
13
    "image": "https://example.com/images/3.jpg",
14
    "title": "Test Three",
15
    "body": "Description Three"
16
  },
17
  ...
18
]

カードを表示するページを作成する


最後にカードを表示するページを作成します。pages以下に適当にページ用のファイルを作成し、asyncDataで先に作成したjsonからデータを取得します。

1
<template>
2
  <div>
3
    <magic-grid>
4
      <card
5
        v-for="(x, i) in data"
6
        :key="i"
7
        :image="x.image"
8
        :title="x.title"
9
        :body="x.body" />
10
    </magic-grid>
11
  </div>
12
</template>
13
14
<script>
15
import card from "../components/Card.vue";
16
17
export default {
18
  name: "grid",
19
  components: {
20
    card
21
  },
22
  async asyncData({ $axios }) {
23
    const imagesData = await $axios.$get(`/data/images.json`);
24
    return { data: imagesData };
25
  }
26
};
27
</script>

表示順をランダムにしたい


ということもあります。自前でシャフルしましょう。

1
export default {
2
  name: "grid",
3
  components: {
4
    card
5
  },
6
  async asyncData({ $axios }) {
7
    let imagesData = await $axios.$get(`/data/images.json`);
8
    for (let i = imagesData.length - 1; i > 0; i--) {
9
      let j = Math.floor(Math.random() * (i + 1));
10
      let tmp = imagesData[i];
11
      imagesData[i] = imagesData[j];
12
      imagesData[j] = tmp;
13
    }
14
    return { data: imagesData };
15
  }
16
};

これでページを表示するたびに異なる順序でカードが表示されるようになります。

その他


後はほかのライブラリと組み合わせてクリックすると全画面表示とかできるようにしたいと思ってます。できたらそのうち続きを書くかもしれません。

おわり。