通过 setInterval 在列表中切换 class 的最简洁方法

Cleanest way to toggle class in list through setInterval

我想切换元素列表中的 'active' class:

<div ref="gallery" class="slider">
  <div class="slide active">
  <div class="slide">
  <div class="slide">
</div>

使用 Vue 和 Vanilla JS

Slider() {
  const slider = document.querySelectorAll('.slider')
  for (const slide of slider) {
    setInterval(function () {
      const current = slide.querySelector('.active')
      current.classList.remove('active')
      const next = current.nextElementSibling || slide.firstElementChild
      next.classList.add('active')
    }, 5000)
  }
}

虽然上面的代码确实有效,但我觉得它还不够干净。

此外,主要是,如果我使用 Vue 引用来定位滑块,例如:

const slider = this.$refs.gallery

它停止工作


tony19 的回答让我使用 Nuxt 进一步减少了代码:

export default {
  data() {
    return {
      activeIndex: 0,
      slides: [
        { id: 1, text: 'Slide 1' },
        { id: 2, text: 'Slide 2' },              
        { id: 3, text: 'Slide 3' },
      ]
    }
  },
  mounted() {
    this.Slider()
  },
  methods: {
    Slider() {
      setInterval(() => {
        this.activeIndex = (this.activeIndex + 1) % this.slides.length
      }, 3000)
    }
  }   
}

<template>
  <div class="slider">
    <div v-for="(slide, index) in slides"
      :key="slide.id"
      :class="['slide', { active: index === activeIndex }]">
      {{ slide.text }}
    </div>
  </div>
</template>

我根据您的要求以 vue.js 格式制作了这个演示。请看看这是否是您真正想要实现的目标。

演示:

new Vue({
  el: '#app',
  data: {
    slideData: [{
        name: 'Slide 1',
      isActive: true
    }, {
        name: 'Slide 2',
      isActive: false    
    }, {
        name: 'Slide 3',
      isActive: false    
    }]
  },
  mounted() {
    this.slideData.forEach((obj) => {
      setInterval(() => {
        obj.isActive = !obj.isActive;
      }, 3000);
    });
  }
})
.active {
  color: white;
  background-color: green;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div v-for="(slider, index) in slideData" class="slide" :class="{ active: slider.isActive }">
  {{ slider.name}}
</div>
</div>

您可以使用 class 绑定,根据活动索引将 class 设置为 active

  1. 声明一个 activeIndex 属性 来保存活动索引。

  2. mounted 挂钩中,使用 setInterval() 和递增 activeIndex 的回调。跟踪来自 setInterval() 的计时器 ID,以便我们稍后可以停止计时器。

  3. unmounted 挂钩中,停止定时器 ID 上带有 clearInterval() 的间隔定时器。

  4. 仅当 activeIndex 与来自 v-for 的幻灯片索引匹配时,才使用 object syntax for class bindings 绑定 active class。 =25=]

<script setup>
import { ref, onMounted, onUnmounted } from 'vue'

let timerId = -1
1️⃣
const activeIndex = ref(0)
const slides = ref([
  { id: 1, text: 'Slide 1' },
  { id: 2, text: 'Slide 2' },
  { id: 3, text: 'Slide 3' },
])

2️⃣
onMounted(() => {
  timerId = setInterval(() => {
    activeIndex.value = (activeIndex.value + 1) % slides.value.length
  }, 3000)
})
3️⃣
onUnmounted(() => {
  clearInterval(timerId)
})
</script>

<template>
  <div ref="gallery" class="slider">
    <div v-for="(slide, index) in slides"
      :key="slide.id"
      class="slide"
      4️⃣
      :class="{ active: index === activeIndex }">
      {{ slide.text }}
    </div>
  </div>
</template>

demo