Vue.jsでのカルーセルスライダー「vue-slick」を使ってみる

ポータルサイトなどコンテンツの多いサイトには何かと使えるカルーセルスライダー。
Bootstrapにも標準で機能がついているので、サイトのトップページに動きを出したい場合など手軽に設置できるようになりました。

しかし、そのBootstrapでは基本的に一度に表示される画像は1枚という仕様のようで、複数のサムネイルを自由にスライドさせたりレスポンシブにするには一工夫必要で、簡単にカスタマイズ……というわけにはいきません。

そこで複数のサムネイルをスライドさせたりレスポンシブ対応させたカルーセルスライダーを組み込みたい場合におすすめの「slick」をご紹介します。

slick

オリジナルはjQueryのプラグインですが、最近の流れに乗ってVue.jsで使えるコンポーネント版ができたようなので、今回はそちらを使って組み込んでみましょう。

staskjs/vue-slick

前提とする環境

# composer.json
- laravel 5.7
- laravel-medialibrary 7.5

# package.json
- vue 2.5.7
- vue-slick 1.1.15

laravelとvueはデフォルトで入っているので問題ないと思います。
laravel-medialibraryは以前紹介した記事を参照してください。(【Laravel定番シリーズ】「laravel-medialibrary」でモデルと画像の関連付け

手順

vue-slick以外は入っているものとして進めていきます。

まずはvue-slickのパッケージをインストールします。

$ npm install vue-slick

これでvue-slickのコンポーネントがインストールされるので、後は使いたい設定のカルーセルスライダー用のコンポーネントを作って読み込むだけになります。

resources/js/components/SlickComponent.vue

<template>
    <slick
    ref="slick"
    :options="slickOptions">
    <div v-for="(image, index) in images" :key="index" class="image-thumb">
        <img :src="image.first_image_url">
    </div>
    </slick>
</template>

<script>
    // vue-slickをインポート
    import Slick from 'vue-slick';
    export default {
        // bladeから受け取るデータを指定
        props: ['images'],
        // コンポーネント使用の宣言
        components: { Slick },
        data() {
            return {
                // slickの設定
                slickOptions: {
                    autoplay: true,
                    dots: true,
                    infinite: true,
                    speed: 300,
                    slidesToShow: 6,
                    slidesToScroll: 3,
                    responsive: [
                        {
                            breakpoint: 992,
                            settings: {
                                slidesToShow: 4,
                                slidesToScroll: 2,
                            }
                        },
                        {
                            breakpoint: 768,
                            settings: {
                                slidesToShow: 4,
                                slidesToScroll: 2
                            }
                        },
                    ]
                },
            };
        },
        methods: {
            next() {
                this.$refs.slick.next();
            },
            prev() {
                this.$refs.slick.prev();
            },
            reInit() {
                this.$nextTick(() => {
                    this.$refs.slick.reSlick();
                });
            },
        },
    }
</script>

vueに慣れていないと分かりづらいかもしれませんが、かなりシンプルに設定が可能です。
slickOptionsの部分に設定を記述することで、スライドを表示する数や自動カルーセル、エンドレス、レスポンシブなど自由に設定することができます。
設定の書き方は公式サイトを参照してください(http://kenwheeler.github.io/slick/

bladeファイルからバインディングしたimagesをpropsで受け取っています。bladeの書き方は後述。

resources/js/app.js

Vue.component('v-slick', require('./components/SlickComponent.vue'));

app.jsに上記を追記して作ったコンポーネントを読み込ませます。

resource/view/index.blade.php

<v-slick v-bind:images="{{ $images }}"></v-slick>

bladeファイルにはv-slickのタグを書くだけでカルーセルスライダーが表示されるようになります。
v-bind:imagesで画像を持ったオブジェクトを渡すようにしているので、スライドされる画像の絞り込みや並び順の管理をコントローラーなどプログラム側でできるようにしています。

app/Http/Controllers/IndexController.php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Image;

class IndexController extends Controller
{
    public function index()
    {
        $images = Image::get();
        return view('index', compact('images'));
    }
}

コントローラーでは、今回はサンプルなのでImageモデルをviewに渡すだけです。

App\Image

namespace App;

use Illuminate\Database\Eloquent\Model;
use Spatie\MediaLibrary\Models\Media;
use Spatie\MediaLibrary\HasMedia\HasMedia;
use Spatie\MediaLibrary\HasMedia\HasMediaTrait;
use Spatie\Image\Manipulations;

class ImageContent extends Model implements HasMedia
{
    // medialibraryのトレイト
    use HasMediaTrait;

    protected $fillable = [
        'file_name',
    ];

    // vueでjsonで受け取れるようにappendsを指定する
    protected $appends = ['first_image_url'];

    public function getFirstImageUrlAttribute()
    {
        return $this->getFirstMediaUrl();
    }

}

Imageモデルはlaravel-medialibraryを継承、トレイトしたモデルです。
ここではすでに画像の保存はしているものとして、getFirstImageUrlAttributeメソッドで画像のURLを取得しています。
そのままだとvueに渡してもURLが取得できないので、appendsを指定してURLを受け取れるようにしておきます。

Vue.jsにするメリット

すでに完成しているコンポーネントを読み込んでいる状態なので、jQueryの場合と比べて特に何か大きく違うかと言われると、Vue.js版の方が多少軽量かもしれませんがあまり違いはないかなという感想です。

Vue.jsとjQueryが混在するのが嫌とか、宗教上の理由でjQueryが使えないなど、明確な理由がある場合は使えると思うので試してみてください。