Nuxt.jsでLightBoxを実装
インストール
npm install vue-image-lightbox vue-lazyload
plugins
/pluginsフォルダ下にインポート用のjsファイルを作成する。
なおこの時点でvue-image-lightboxはimportしない(後述)
例)/plugins/main.js
import Vue from 'vue' import VueLazyLoad from 'vue-lazyload' Vue.use(VueLazyLoad)
nuxt.config.js
設置したプラグインファイルの読み込みをnuxt.config.jsに記述する
plugins: [ { src: '~/plugins/main.js' }, ],
Vueファイル
使用するページのVueファイルに以下を記述
script
<script> require("vue-image-lightbox/dist/vue-image-lightbox.min.css")//css読み込み export default { components: { LightBox:() => process.client ? import('vue-image-lightbox') : null, }, data() { return { media: [ { tuhmb:"サムネイル画像のパス", src:"画像のパス" }, ], } }, methods: { showLightbox(index) { this.$refs.lightbox.showImage(index); }, } } </script>
vue-image-lightboxのimportとcomponent指定
上記の以下の部分についての理由を詳述
components: {
LightBox:() => process.client ? import('vue-image-lightbox') : null,
},
SSRエラーの回避
vue-image-lightboxはコード内にwindowを使用しているため、SSR(サーバーサイドレンダリング)ではエラーとなる。そこでクライアント側でだけimportするよう、component定義時にprocess.clientでの判定を噛ませて読み込みを行っている。
lazy-lordの読み込みのように別ファイルにしてnuxt.config.jsのpluginsのパラメータとしてmode:’client’を使用する方法もあり、試したところimportは問題ないがcomponent定義がうまくいかず断念。
plugins: [ { src: '~/plugins/vue-image-lightbox.js', mode: 'client' } ]
typeエラーの回避
vue-image-lightboxには型定義が無いため、通常のimportを行うとTypeScriptのtypeエラーが発生するが、この記述によりそのエラーも回避できる。
TypeScriptの型定義エラーについては以下のような対処法があるが、今回は上記記述のみで回避できたため以下の対応は行っていない。※しかも現状で理屈を十分に理解できてない
メモとして残しておく。
@typesからインストールする。
具体的には以下。
npm install --save @types/vue-image-lightbox
実行するとエラーとなるので、vue-image-lightboxでは型定義ファイルは提供されていないと思われる。
型定義ファイル( d.ts )を自作する
今回は試していない。
requireでモジュールを読み込む
具体的には以下。
const LightBox = require('vue-image-lightbox')
これによりコンパイルエラーは回避できたが、上記のSSRエラーはいずれにしろ回避できないため使用せず。
テンプレート
mediaという配列に表示する画像のサムネイル、画像のパスがオブジェクト形式で格納されているという前提で、以下のように記述する。
<template> <div class="container"> <div v-for="(image, index) in media" :key="index"> <img :src="'/images/' + image + '.jpg'" alt="" @click="showLightbox(index)"> </div> <client-only> <LightBox ref="lightbox" :media="images" :showLightBox="false" :showThumbs="false" ></LightBox> </client-only> </div> </template>
画像一覧オブジェクトの形式は以下。
[ { thumb: 'http://example.com/thumb.jpg', src: 'http://example.com/image.jpg', caption: 'caption to display. receive <html> <b>tag</b>', // Optional srcset: '...' // Optional for displaying responsive images }, ]
LightBoxコンポーネントについてはクライアント側でのみ読み込まれるので、テンプレート側でもクライアント側での処理となる記述を加える。
<client-only> コンポーネント </client-only>
以上でいけるはず。なんか忘れてたらまた追記。