告别轮播状态混乱:vue-awesome-swiper与Vuex集成的7种实战模式

【免费下载链接】vue-awesome-swiper 🏆 Swiper component for @vuejs 【免费下载链接】vue-awesome-swiper 项目地址: https://gitcode.com/gh_mirrors/vu/vue-awesome-swiper

你是否还在为轮播组件的状态管理头疼?当轮播遇到复杂的状态共享需求,传统的组件内状态管理往往导致数据流混乱、组件通信复杂、状态同步延迟等问题。本文将系统讲解如何通过Vuex(Vue状态管理模式,State Management Pattern)实现vue-awesome-swiper的优雅状态管理,提供从基础集成到高级优化的完整解决方案。读完本文,你将掌握7种实用集成模式、4类状态设计方案、3套性能优化策略,彻底解决轮播组件的状态管理难题。

一、现状诊断:轮播状态管理的3大痛点与解决方案

1.1 痛点分析:为什么需要Vuex管理轮播状态?

痛点场景 传统解决方案 问题表现 Vuex解决方案
多组件共享轮播数据 Props层层传递 代码冗余、维护困难 集中式状态存储
跨组件控制轮播行为 事件总线(Event Bus) 事件命名冲突、调试困难 Action统一调度
异步数据驱动轮播 组件内异步处理 状态更新延迟、闪烁 异步Action+Mutation

1.2 技术选型:为什么选择vue-awesome-swiper?

vue-awesome-swiper是基于Swiper的Vue组件封装,尽管已被官方Swiper Vue组件替代(v5版本起仅作为swiper/vue的桥接),但其在Vue2项目中的广泛应用和稳定表现仍使其成为值得学习的案例。本文将基于vue-awesome-swiper@5(兼容Swiper 7-8,支持Vue3)进行讲解,所有模式同样适用于官方Swiper Vue组件。

mermaid

二、环境准备:快速搭建集成开发环境

2.1 安装依赖

# 安装核心依赖
npm install vue-awesome-swiper@5 swiper@8 vuex@4 --save

# 或使用yarn
yarn add vue-awesome-swiper@5 swiper@8 vuex@4

2.2 基础配置

main.js

import { createApp } from 'vue'
import { createStore } from 'vuex'
import App from './App.vue'
import VueAwesomeSwiper from 'vue-awesome-swiper'
import 'swiper/css'
import 'swiper/css/pagination'

// 创建Vuex store
const store = createStore({
  state() {
    return {
      swiperState: {
        activeIndex: 0,
        slides: [],
        isPlaying: false
      }
    }
  }
})

const app = createApp(App)
app.use(store)
app.use(VueAwesomeSwiper)
app.mount('#app')

三、核心模式:7种Vuex集成方案全解析

3.1 模式一:基础状态同步模式

核心思想:通过Vuex存储轮播的基础状态(当前索引、播放状态),实现组件间状态共享。

Store模块 (store/modules/swiper.js)

export default {
  namespaced: true,
  state: {
    activeIndex: 0,
    isPlaying: false,
    slides: []
  },
  mutations: {
    SET_ACTIVE_INDEX(state, index) {
      state.activeIndex = index
    },
    TOGGLE_PLAY(state, status) {
      state.isPlaying = status !== undefined ? status : !state.isPlaying
    },
    SET_SLIDES(state, slides) {
      state.slides = slides
    }
  }
}

轮播组件 (components/SyncSwiper.vue)

<template>
  <Swiper 
    :modules="modules" 
    :pagination="{ clickable: true }"
    @slide-change="handleSlideChange"
    :autoplay="isPlaying ? { delay: 3000 } : false"
  >
    <SwiperSlide v-for="(slide, index) in slides" :key="index">
      <img :src="slide.url" :alt="slide.title">
    </SwiperSlide>
  </Swiper>
</template>

<script setup>
import { computed, watch } from 'vue'
import { useStore } from 'vuex'
import { Pagination, Autoplay } from 'swiper'

const store = useStore()
const modules = [Pagination, Autoplay]

// 从Vuex获取状态
const slides = computed(() => store.state.swiper.slides)
const isPlaying = computed(() => store.state.swiper.isPlaying)
const activeIndex = computed(() => store.state.swiper.activeIndex)

// 监听自动播放状态变化
watch(isPlaying, (newVal) => {
  if (newVal) {
    swiperRef.value.swiper.autoplay.start()
  } else {
    swiperRef.value.swiper.autoplay.stop()
  }
})

// 处理滑动事件,更新Vuex状态
const handleSlideChange = (swiper) => {
  store.commit('swiper/SET_ACTIVE_INDEX', swiper.activeIndex)
}
</script>

3.2 模式二:Action异步加载模式

核心思想:通过Vuex Action处理异步数据加载,实现轮播数据的集中式获取与分发。

Store模块增强

// 添加Actions处理异步逻辑
actions: {
  // 加载轮播数据
  async fetchSlides({ commit }, apiUrl) {
    try {
      commit('SET_LOADING', true)
      const response = await fetch(apiUrl)
      const data = await response.json()
      commit('SET_SLIDES', data.slides)
      // 数据加载完成后自动播放
      commit('TOGGLE_PLAY', true)
    } catch (error) {
      console.error('轮播数据加载失败:', error)
      commit('SET_ERROR', error.message)
    } finally {
      commit('SET_LOADING', false)
    }
  },
  
  // 控制轮播切换
  async changeSlide({ commit, state }, index) {
    // 范围检查
    if (index < 0 || index >= state.slides.length) return
    
    // 停止自动播放
    commit('TOGGLE_PLAY', false)
    
    // 等待下一个tick确保状态更新
    await new Promise(resolve => setTimeout(resolve, 0))
    
    // 返回新索引供组件使用
    return index
  }
}

使用示例

<script setup>
import { onMounted } from 'vue'
import { useStore } from 'vuex'

const store = useStore()

onMounted(() => {
  // 从API加载轮播数据
  store.dispatch('swiper/fetchSlides', '/api/slides')
})

// 外部控制轮播切换
const goToSlide = async (index) => {
  const newIndex = await store.dispatch('swiper/changeSlide', index)
  swiperRef.value.swiper.slideTo(newIndex)
}
</script>

3.3 模式三:Getter计算属性模式

核心思想:利用Vuex Getter派生轮播状态,实现复杂状态逻辑的复用。

Store Getter实现

getters: {
  // 获取当前激活的幻灯片
  activeSlide(state) {
    return state.slides[state.activeIndex] || null
  },
  
  // 计算轮播进度百分比
  progressPercentage(state) {
    if (state.slides.length === 0) return 0
    return ((state.activeIndex + 1) / state.slides.length) * 100
  },
  
  // 检查是否可以切换到上一张/下一张
  hasPrevNext(state) {
    return {
      hasPrev: state.activeIndex > 0,
      hasNext: state.activeIndex < state.slides.length - 1
    }
  },
  
  // 过滤有效幻灯片
  validSlides(state) {
    return state.slides.filter(slide => slide && slide.url)
  }
}

组件中使用Getter

<template>
  <div class="swiper-controls">
    <button 
      @click="prevSlide" 
      :disabled="!hasPrevNext.hasPrev"
    >
      上一张
    </button>
    
    <div class="progress-bar">
      <div :style="{ width: progressPercentage + '%' }"></div>
    </div>
    
    <button 
      @click="nextSlide" 
      :disabled="!hasPrevNext.hasNext"
    >
      下一张
    </button>
  </div>
  
  <div class="active-slide-info" v-if="activeSlide">
    <h3>{{ activeSlide.title }}</h3>
    <p>{{ activeSlide.description }}</p>
  </div>
</template>

<script setup>
import { computed } from 'vue'
import { useStore } from 'vuex'

const store = useStore()

// 使用Getter获取派生状态
const activeSlide = computed(() => store.getters['swiper/activeSlide'])
const progressPercentage = computed(() => store.getters['swiper/progressPercentage'])
const hasPrevNext = computed(() => store.getters['swiper/hasPrevNext'])
</script>

3.4 模式四:Module模块化模式

核心思想:通过Vuex Module实现多个轮播实例的独立状态管理,解决多轮播共存时的状态冲突。

目录结构设计

store/
├── modules/
│   ├── homeSwiper.js    # 首页轮播模块
│   ├── productSwiper.js # 产品轮播模块
│   └── commonSwiper.js  # 通用轮播模块
└── index.js             # 组合模块

模块配置示例 (homeSwiper.js)

// 首页轮播模块
export default {
  namespaced: true,
  state: {
    slides: [],
    activeIndex: 0,
    config: {
      autoplay: { delay: 5000 },
      pagination: { clickable: true },
      loop: true
    }
  },
  mutations: {
    // 模块专用mutations
    SET_SLIDES(state, slides) {
      state.slides = slides
    },
    SET_ACTIVE_INDEX(state, index) {
      state.activeIndex = index
    }
  },
  actions: {
    // 模块专用actions
    async fetchHomeSlides({ commit }) {
      const response = await fetch('/api/home-slides')
      const data = await response.json()
      commit('SET_SLIDES', data)
    }
  }
}

多轮播页面使用

<template>
  <div class="home-page">
    <!-- 首页轮播 -->
    <SwiperModule 
      moduleName="homeSwiper" 
      apiUrl="/api/home-slides"
    />
    
    <!-- 产品轮播 -->
    <SwiperModule 
      moduleName="productSwiper" 
      apiUrl="/api/product-slides"
    />
  </div>
</template>

<script setup>
// 通用轮播模块组件
import SwiperModule from '@/components/SwiperModule.vue'
</script>

3.5 模式五:插件封装模式

核心思想:将轮播的Vuex集成逻辑封装为Vue插件,实现跨项目复用。

插件封装 (plugins/swiperVuex.js)

export default {
  install(app, options = {}) {
    // 默认配置
    const defaultOptions = {
      moduleName: 'swiper',
      autoRegisterModule: true
    }
    
    const finalOptions = { ...defaultOptions, ...options }
    
    // 如果需要自动注册模块
    if (finalOptions.autoRegisterModule && app.config.globalProperties.$store) {
      app.config.globalProperties.$store.registerModule(
        finalOptions.moduleName,
        // 轮播模块定义
        {
          namespaced: true,
          state: { /* 状态定义 */ },
          mutations: { /* 变更方法 */ },
          actions: { /* 动作方法 */ },
          getters: { /* 计算属性 */ }
        }
      )
    }
    
    // 注册全局组件
    app.component('SwiperVuex', {
      // 全局轮播组件定义
      props: ['moduleName'],
      // ...组件实现
    })
  }
}

插件使用

// main.js中注册插件
import swiperVuexPlugin from './plugins/swiperVuex'

// 自定义配置
app.use(swiperVuexPlugin, {
  moduleName: 'carousel',
  autoRegisterModule: true
})

3.6 模式六:Composition API模式

核心思想:结合Vue3 Composition API与Vuex,实现轮播逻辑的组合式复用。

组合式函数 (composables/useSwiperStore.js)

import { computed, ref, onMounted, onUnmounted } from 'vue'
import { useStore } from 'vuex'

export function useSwiperStore(moduleName = 'swiper') {
  const store = useStore()
  const swiperRef = ref(null)
  
  // 状态映射
  const state = {
    slides: computed(() => store.state[moduleName].slides),
    activeIndex: computed(() => store.state[moduleName].activeIndex),
    isPlaying: computed(() => store.state[moduleName].isPlaying)
  }
  
  // 方法映射
  const actions = {
    fetchSlides: (url) => store.dispatch(`${moduleName}/fetchSlides`, url),
    togglePlay: () => store.commit(`${moduleName}/TOGGLE_PLAY`),
    setActiveIndex: (index) => store.commit(`${moduleName}/SET_ACTIVE_INDEX`, index)
  }
  
  // 事件处理
  const handleSlideChange = (swiper) => {
    actions.setActiveIndex(swiper.activeIndex)
  }
  
  // 生命周期钩子
  onMounted(() => {
    // 初始化逻辑
  })
  
  onUnmounted(() => {
    // 清理逻辑
  })
  
  return {
    swiperRef,
    ...state,
    ...actions,
    handleSlideChange
  }
}

在组件中使用组合式函数

<template>
  <Swiper 
    ref="swiperRef"
    :modules="modules"
    @slide-change="handleSlideChange"
    :autoplay="isPlaying ? { delay: 3000 } : false"
  >
    <!-- 轮播内容 -->
  </Swiper>
</template>

<script setup>
import { useSwiperStore } from '@/composables/useSwiperStore'
import { Pagination, Autoplay } from 'swiper'

// 使用组合式函数,指定模块名
const {
  swiperRef,
  slides,
  activeIndex,
  isPlaying,
  fetchSlides,
  togglePlay,
  handleSlideChange
} = useSwiperStore('homeSwiper')

// 加载轮播数据
fetchSlides('/api/home-slides')
</script>

3.7 模式七:严格模式与测试模式

核心思想:在开发环境启用Vuex严格模式,结合单元测试确保轮播状态变更的可预测性。

Store配置

// store/index.js
const store = createStore({
  // 开发环境启用严格模式
  strict: process.env.NODE_ENV !== 'production',
  modules: {
    swiper: swiperModule
  }
})

单元测试示例

// tests/unit/swiperStore.spec.js
import { createStore } from 'vuex'
import swiperModule from '@/store/modules/swiper'

describe('Swiper Vuex Module', () => {
  let store
  
  beforeEach(() => {
    store = createStore({
      modules: {
        swiper: { ...swiperModule }
      }
    })
  })
  
  test('should set active index correctly', () => {
    store.commit('swiper/SET_ACTIVE_INDEX', 2)
    expect(store.state.swiper.activeIndex).toBe(2)
  })
  
  test('should toggle play state', () => {
    // 初始状态
    expect(store.state.swiper.isPlaying).toBe(false)
    
    // 第一次切换
    store.commit('swiper/TOGGLE_PLAY')
    expect(store.state.swiper.isPlaying).toBe(true)
    
    // 第二次切换
    store.commit('swiper/TOGGLE_PLAY')
    expect(store.state.swiper.isPlaying).toBe(false)
    
    // 直接设置状态
    store.commit('swiper/TOGGLE_PLAY', true)
    expect(store.state.swiper.isPlaying).toBe(true)
  })
  
  // 异步Action测试
  test('should fetch slides correctly', async () => {
    // Mock fetch
    global.fetch = jest.fn().mockResolvedValue({
      json: () => Promise.resolve({ slides: [{ id: 1 }, { id: 2 }] })
    })
    
    await store.dispatch('swiper/fetchSlides', '/test-api')
    
    // 验证状态已更新
    expect(store.state.swiper.slides.length).toBe(2)
    expect(store.state.swiper.isPlaying).toBe(true)
  })
})

四、状态设计:4类轮播状态的最佳实践

4.1 基础状态设计

基础状态包括轮播的核心数据和控制标志,建议设计如下:

state: {
  // 轮播数据
  slides: [],             // 幻灯片数组
  activeIndex: 0,         // 当前激活索引
  prevIndex: -1,          // 上一个索引(用于过渡动画)
  
  // 控制状态
  isPlaying: false,       // 是否自动播放
  isLoading: false,       // 是否加载中
  isError: false,         // 是否出错
  errorMessage: '',       // 错误信息
  
  // 尺寸状态
  containerWidth: 0,      // 容器宽度
  containerHeight: 0      // 容器高度
}

4.2 配置状态设计

将轮播配置也存储在Vuex中,实现动态配置:

state: {
  // 基础配置
  config: {
    autoplay: { delay: 3000 },
    pagination: { clickable: true },
    navigation: true,
    loop: false,
    speed: 300
  },
  
  // 响应式断点配置
  breakpoints: {
    640: { slidesPerView: 1 },
    768: { slidesPerView: 2 },
    1024: { slidesPerView: 3 }
  }
}

4.3 统计状态设计

添加统计状态追踪轮播使用情况:

state: {
  // 交互统计
  interactionStats: {
    slideCount: 0,         // 滑动次数
    clickCount: 0,         // 点击次数
    startTimestamp: null,  // 开始时间戳
    totalPlayTime: 0       // 总播放时间
  }
}

// 对应的mutations
mutations: {
  INCREMENT_SLIDE_COUNT(state) {
    state.interactionStats.slideCount++
  },
  INCREMENT_CLICK_COUNT(state) {
    state.interactionStats.clickCount++
  },
  UPDATE_PLAY_TIME(state) {
    if (state.interactionStats.startTimestamp) {
      const now = Date.now()
      state.interactionStats.totalPlayTime += now - state.interactionStats.startTimestamp
      state.interactionStats.startTimestamp = now
    }
  }
}

4.4 历史记录状态设计

实现轮播浏览历史记录功能:

state: {
  history: {
    visited: [],           // 访问过的幻灯片ID
    position: -1,          // 当前历史位置
    maxLength: 20          // 最大历史记录长度
  }
}

actions: {
  // 添加到历史记录
  addToHistory({ state, commit }, slideId) {
    // 限制历史记录长度
    if (state.history.visited.length >= state.history.maxLength) {
      commit('TRIM_HISTORY')
    }
    
    // 如果不是重复项才添加
    if (!state.history.visited.includes(slideId)) {
      commit('ADD_HISTORY_ITEM', slideId)
    }
  }
}

五、性能优化:3大策略提升轮播体验

5.1 状态更新优化

问题:频繁的状态更新会导致性能问题,特别是在大型应用中。

解决方案

  1. 批量更新状态:使用Action合并多个状态更新
actions: {
  // 批量更新轮播状态
  batchUpdateSwiper({ commit }, updates) {
    // 使用Object.entries遍历更新对象
    Object.entries(updates).forEach(([key, value]) => {
      const mutation = `SET_${key.toUpperCase()}`
      if (typeof commit(mutation) === 'function') {
        commit(mutation, value)
      }
    })
  }
}

// 使用方式
store.dispatch('swiper/batchUpdateSwiper', {
  activeIndex: 2,
  isPlaying: true,
  containerWidth: 800
})
  1. 防抖状态更新:对高频事件进行防抖处理
import { debounce } from 'lodash'

// 在组件中防抖处理滑动事件
const handleSlideChange = debounce((swiper) => {
  store.commit('swiper/SET_ACTIVE_INDEX', swiper.activeIndex)
}, 100)

5.2 渲染优化

解决方案

  1. 虚拟列表:只渲染可见区域的幻灯片
<template>
  <Swiper 
    :modules="modules"
    :virtual="true"  <!-- 启用虚拟滑动 -->
  >
    <SwiperSlide
      v-for="slide in visibleSlides"
      :key="slide.id"
      :virtualIndex="slide.virtualIndex"
    >
      <!-- 幻灯片内容 -->
    </SwiperSlide>
  </Swiper>
</template>
  1. 懒加载:配合Vuex实现图片懒加载
actions: {
  // 预加载可见区域附近的图片
  preloadNearbyImages({ state }, { index, distance = 2 }) {
    const start = Math.max(0, index - distance)
    const end = Math.min(state.slides.length, index + distance + 1)
    
    for (let i = start; i < end; i++) {
      const slide = state.slides[i]
      if (slide && slide.url && !slide.loaded) {
        // 预加载图片
        const img = new Image()
        img.src = slide.url
        img.onload = () => {
          commit('MARK_SLIDE_LOADED', i)
        }
      }
    }
  }
}

5.3 内存优化

解决方案

  1. 组件卸载时清理
// 在组件unmounted时
onUnmounted(() => {
  // 停止自动播放
  store.commit('swiper/TOGGLE_PLAY', false)
  
  // 清除定时器
  if (timer.value) {
    clearInterval(timer.value)
  }
  
  // 重置状态(如果需要)
  if (props.resetOnUnmount) {
    store.commit('swiper/RESET_STATE')
  }
})
  1. 大型数据分片加载
actions: {
  // 分片加载大型轮播数据
  async fetchSlidesInChunks({ commit }, { url, chunkSize = 5 }) {
    commit('SET_LOADING', true)
    
    try {
      const response = await fetch(url)
      const totalSlides = await response.json()
      
      // 分片提交数据
      for (let i = 0; i < totalSlides.length; i += chunkSize) {
        const chunk = totalSlides.slice(i, i + chunkSize)
        commit('ADD_SLIDES_CHUNK', chunk)
        
        // 每加载一个分片暂停一下,避免阻塞UI
        if (i < totalSlides.length - chunkSize) {
          await new Promise(resolve => setTimeout(resolve, 50))
        }
      }
    } catch (error) {
      commit('SET_ERROR', error.message)
    } finally {
      commit('SET_LOADING', false)
    }
  }
}

六、常见问题与解决方案

6.1 状态同步延迟问题

问题:轮播滑动后,Vuex状态更新延迟导致UI不同步。

解决方案:使用sync修饰符或自定义同步逻辑:

// 在轮播组件中使用nextTick确保DOM更新后再同步状态
const handleSlideChange = (swiper) => {
  nextTick(() => {
    store.commit('swiper/SET_ACTIVE_INDEX', swiper.activeIndex)
  })
}

6.2 多实例冲突问题

问题:多个轮播实例共存时状态相互干扰。

解决方案:使用模块化命名空间和作用域隔离:

// 确保每个轮播模块使用独立的命名空间
store.registerModule('homeSwiper', homeSwiperModule)
store.registerModule('productSwiper', productSwiperModule)

// 在组件中指定模块名
const slides = computed(() => store.state.homeSwiper.slides)

6.3 异步数据加载问题

问题:异步加载数据后,轮播实例未正确更新。

解决方案:使用key属性强制重新渲染:

<template>
  <Swiper 
    :key="slides.length"  <!-- 数据变化时重新创建实例 -->
    :modules="modules"
  >
    <!-- 幻灯片内容 -->
  </Swiper>
</template>

七、总结与展望

本文详细介绍了vue-awesome-swiper与Vuex集成的7种实战模式,从基础状态同步到高级插件封装,全面覆盖了轮播状态管理的各种场景。通过合理应用这些模式,你可以解决轮播组件的状态共享、异步数据处理、跨组件通信等核心问题,构建出更健壮、可维护的轮播功能。

随着Vue3和Pinia(Vuex的继任者)的普及,未来轮播状态管理将更加简洁高效。建议关注以下发展方向:

  1. Pinia集成:Pinia提供更简洁的API和更好的TypeScript支持,适合替代Vuex
  2. 组合式API深化:进一步利用Vue3的Composition API简化轮播逻辑
  3. 状态规范化:借鉴数据库范式思想,优化轮播状态结构
  4. 服务端状态同步:结合SSR/SSG技术,实现服务端与客户端轮播状态同步

希望本文提供的方案能帮助你解决实际项目中的轮播状态管理问题。如果觉得本文对你有帮助,请点赞、收藏、关注三连支持,下期我们将探讨轮播组件的单元测试与自动化测试策略。

附录:完整Store模块代码

完整的轮播Vuex模块代码可在以下位置获取:

// store/modules/swiper.js 完整代码
const state = {
  slides: [],
  activeIndex: 0,
  isPlaying: false,
  isLoading: false,
  isError: false,
  errorMessage: '',
  config: {
    autoplay: { delay: 3000 },
    pagination: { clickable: true },
    loop: false
  },
  interactionStats: {
    slideCount: 0,
    clickCount: 0
  }
}

const mutations = {
  SET_SLIDES(state, slides) {
    state.slides = slides
  },
  SET_ACTIVE_INDEX(state, index) {
    state.prevIndex = state.activeIndex
    state.activeIndex = index
  },
  TOGGLE_PLAY(state, status) {
    state.isPlaying = status !== undefined ? status : !state.isPlaying
  },
  SET_LOADING(state, status) {
    state.isLoading = status
  },
  SET_ERROR(state, message) {
    state.isError = !!message
    state.errorMessage = message || ''
  },
  UPDATE_CONFIG(state, config) {
    state.config = { ...state.config, ...config }
  },
  INCREMENT_SLIDE_COUNT(state) {
    state.interactionStats.slideCount++
  },
  INCREMENT_CLICK_COUNT(state) {
    state.interactionStats.clickCount++
  }
}

const actions = {
  async fetchSlides({ commit }, url) {
    commit('SET_LOADING', true)
    commit('SET_ERROR', '')
    
    try {
      const response = await fetch(url)
      if (!response.ok) throw new Error('请求失败')
      
      const data = await response.json()
      commit('SET_SLIDES', data.slides || [])
      commit('TOGGLE_PLAY', true)
    } catch (error) {
      commit('SET_ERROR', error.message)
      console.error('轮播数据加载失败:', error)
    } finally {
      commit('SET_LOADING', false)
    }
  },
  
  async changeSlide({ commit, state }, index) {
    if (index < 0 || index >= state.slides.length) return
    
    commit('SET_ACTIVE_INDEX', index)
    commit('INCREMENT_SLIDE_COUNT')
    
    // 如果不是自动播放状态,切换后暂停
    if (!state.isPlaying) {
      commit('TOGGLE_PLAY', false)
    }
  }
}

const getters = {
  activeSlide: state => state.slides[state.activeIndex] || null,
  slideCount: state => state.slides.length,
  hasSlides: state => state.slides.length > 0,
  progress: state => state.slides.length 
    ? (state.activeIndex / (state.slides.length - 1)) * 100 
    : 0
}

export default {
  namespaced: true,
  state,
  mutations,
  actions,
  getters
}

【免费下载链接】vue-awesome-swiper 🏆 Swiper component for @vuejs 【免费下载链接】vue-awesome-swiper 项目地址: https://gitcode.com/gh_mirrors/vu/vue-awesome-swiper

更多推荐