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>
以上でいけるはず。なんか忘れてたらまた追記。