🌐

【Vue.js】Vue.jsでslickが動的なスライドショーを作成してくれない件

2022/02/02に公開

概要

Vue.jsにてスライドショーを手軽に実装するにあたってよく使われているスライダープラグイン「slick」使用時に沼った現象があったので備忘録として残す。

メインスライドの下にサムネイル画像が表示するスライドショーを作りたい
(スライドの数は動的、変化する)
しかし、下記1、2部分で動作確認すると二回目表示以降メイン画像がスライドショーにならず縦一列に表示されたり、表示されなかったりという挙動になった

下記一部抜粋
1:html部分

<slick
  ref="slick"
  :options="slickOptions"
  class="slider-for">
  <div
    v-for="(item, index) in eventItem.image"
    :key="index"
    class="item-image">
    <img
      :src="item">
   </div>
</slick>
<slick
 ref="slickNav"
 :options="slickNavOptions"
 class="slider-nav">
  <div
   v-for="(item, index) in eventItem.image"
   :key="index"
   class="item-tmb">
   <img
     :src="item">
  </div>
</slick>

2:js部分一部抜粋

export default {
  data () {
    return {
      slickOptions: {
        slidesToShow: 1,
        arrows: false,
        autoplay: true,
        asNavFor: '.slider-nav'
      },
      slickNavOptions: {
        slidesToShow: 5,
        asNavFor: '.slider-for',
        focusOnSelect: true
      }
    }
  },

解決方法

結論としてはVue.jsの仕様で最適にレンダリングしようとして前回のスリックのDOMを使いまわそうとしてしまい、その状態でスリックが生成されるため期待値で表示されないのだろうという推測に至った…

つまり、Vueインスタンス生成後にスリックを再描画してあげる、かつ、Vueインスタンスが破棄される時にスリックも破棄してあげることが必要(間違っていたら申し訳ない…)

具体的には下記を参照

this.$refs.slick

↑の部分のslickは各々でhtmlでref="○○"としたところと一致させる必要がある。

methods: {
    reInit () {
      this.$nextTick(() => {
        this.$refs.slick.reSlick()
        this.$refs.slickNav.reSlick()
      })
    }
  },
  beforeUpdate () {
    if (this.$refs.slick) {
      this.$refs.slick.destroy()
      this.$refs.slickNav.destroy()
    }
  },
  updated () {
    if (this.$refs.slick && !this.$refs.slick.$el.classList.contains('slick-initialized')) {
      this.$nextTick(() => {
        this.$refs.slick.create(this.slickOptions)
        this.$refs.slickNav.create(this.slickOptions)
      })
    }
  },
  activated () {
    if (this.$refs.slick) {
      this.$refs.slick.destroy()
      this.$refs.slickNav.destroy()
    }
    if (this.$refs.slick && !this.$refs.slick.$el.classList.contains('slick-initialized')) {
      this.$nextTick(() => {
        this.$refs.slick.create(this.slickOptions)
        this.$refs.slickNav.create(this.slickNavOptions)
      })
    }
  }

冗長感否めないが、動いたから良しとする。

Discussion