Maison > Article > interface Web > Comment utiliser vue3+Pinia+TypeScript pour implémenter un composant carrousel encapsulé
Répond aux idées de développement modulaire es6
Enregistré en tant que composant global pour une meilleure réutilisation, partout où vous en avez besoin pour l'utiliser, utilisez simplement le tag directement
<script lang="ts" setup name="XtxCarousel"> defineProps() </script> <template> <div class="xtx-carousel"> <ul class="carousel-body"> <li class="carousel-item fade"> <RouterLink to="/"> <img src="https://cache.yisu.com/upload/information/20220725/112/220.jpg" alt="" /> </RouterLink> </li> <li class="carousel-item"> <RouterLink to="/"> <img src="https://cache.yisu.com/upload/information/20220725/112/220.jpg" alt="" /> </RouterLink> </li> <li class="carousel-item"> <RouterLink to="/"> <img src="https://cache.yisu.com/upload/information/20220725/112/220.jpg" alt="" /> </RouterLink> </li> </ul> <a href="javascript:;" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" class="carousel-btn prev" ><i class="iconfont icon-angle-left"></i ></a> <a href="javascript:;" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" class="carousel-btn next" ><i class="iconfont icon-angle-right"></i ></a> <div class="carousel-indicator"> <span class="active"></span> <span></span> <span></span> <span></span> <span></span> </div> </div> </template> <style scoped lang="less"> .xtx-carousel { width: 100%; height: 100%; min-width: 300px; min-height: 150px; position: relative; .carousel { &-body { width: 100%; height: 100%; } &-item { width: 100%; height: 100%; position: absolute; left: 0; top: 0; opacity: 0; transition: opacity 0.5s linear; &.fade { opacity: 1; z-index: 1; } img { width: 100%; height: 100%; } } &-indicator { position: absolute; left: 0; bottom: 20px; z-index: 2; width: 100%; text-align: center; span { display: inline-block; width: 12px; height: 12px; background: rgba(0, 0, 0, 0.2); border-radius: 50%; cursor: pointer; ~ span { margin-left: 12px; } &.active { background: #fff; } } } &-btn { width: 44px; height: 44px; background: rgba(0, 0, 0, 0.2); color: #fff; border-radius: 50%; position: absolute; top: 228px; z-index: 2; text-align: center; line-height: 44px; opacity: 0; transition: all 0.5s; &.prev { left: 20px; } &.next { right: 20px; } } } &:hover { .carousel-btn { opacity: 1; } } } </style>
import { defineStore } from 'pinia' import request from '@/utils/request' import { BannerItem, IApiRes } from '@/types/data' export default defineStore('home', { persist: { enabled: true }, state() { return { bannerList: [] as BannerItem[] } }, actions: { // 拿轮播图数据 async getBannerList() { const res = await request.get<IApiRes<BannerItem[]>>('/home/banner') console.log('拿轮播图数据', res) this.bannerList = res.data.result } } })
// 所有的接口的通用类型 export interface IApiRes<T> { msg: string, result: T } // 轮播图数据中的项 export type BannerItem = { id: string; imgUrl: string; hrefUrl: string; type: string; }
<script lang="ts" setup> import useStore from '@/store'; const { home } = useStore() // 发请求 home.getBannerList() </script> <template> <div class="home-banner"> <!-- 轮播图子组件 --> <XtxCarousel :slides="home.bannerList" :autoPlay="true" :duration="1000"/> </div> </template> <style scoped lang="less"> .home-banner { width: 1240px; height: 450px; position: absolute; left: 0; top: 0; z-index: 98; background-color: #ccc; } /deep/ .xtx-carousel .carousel-btn.prev { left: 270px !important; } /deep/ .xtx-carousel .carousel-indicator { padding-left: 250px; } </style>
<script lang="ts" setup name="XtxCarousel"> import { BannerItem } from '@/types/data' import { onBeforeUnmount, onMounted, ref } from 'vue'; // 定义props const { slides, autoPlay, duration } = defineProps<{ slides: BannerItem[], autoPlay?: boolean, // 是否开启自动播放 duration?: number // 自动播放的间隔时间 }>() // 当前哪个图片选中 高亮 const active = ref(1) // 点击右侧箭头++ const hNext = () => { active.value++ if(active.value === slides.length){ active.value = 0 } } // 点击左侧箭头-- const hPrev = () => { active.value-- if(active.value < 0){ active.value = slides.length - 1 } } // 如果开启了自动播放,则每隔duration去播放下一张: hNext() onMounted(() => { start() }) onBeforeUnmount(() => { stop() }) let timer = -1 // 鼠标离开要继续播放 const start = () => { if(autoPlay) { timer = window.setInterval(() => { hNext() }, duration) } } // 鼠标hover要暂停播放 const stop = () => { clearInterval(timer) } </script> <template> <div class="xtx-carousel" @mouseleave="start()" @mouseenter="stop()"> <ul class="carousel-body"> <li class="carousel-item" :class="{ fade: idx === active}" v-for="(it, idx) in slides" :key="it.id"> <RouterLink to="/"> <img :src="it.imgUrl" alt="" /> </RouterLink> </li> </ul> <a @click="hPrev" href="javascript:;" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" class="carousel-btn prev"><i class="iconfont icon-angle-left"></i></a> <a @click="hNext" href="javascript:;" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" class="carousel-btn next"><i class="iconfont icon-angle-right"></i></a> <div class="carousel-indicator"> <span v-for="(it, idx) in slides" :class="{ active: active===idx}" @mouseenter="active = idx" ></span> </div> </div> </template> <style scoped lang="less"> .xtx-carousel { width: 100%; height: 100%; min-width: 300px; min-height: 150px; position: relative; .carousel { &-body { width: 100%; height: 100%; } &-item { width: 100%; height: 100%; position: absolute; left: 0; top: 0; opacity: 0; // 不可见 transition: opacity 0.5s linear; &.fade { opacity: 1; // 可见 z-index: 1; } img { width: 100%; height: 100%; } } &-indicator { position: absolute; left: 0; bottom: 20px; z-index: 2; width: 100%; text-align: center; span { display: inline-block; width: 12px; height: 12px; background: rgba(0, 0, 0, 0.2); border-radius: 50%; cursor: pointer; ~ span { margin-left: 12px; } &.active { background: #fff; } } } &-btn { width: 44px; height: 44px; background: rgba(0, 0, 0, 0.2); color: #fff; border-radius: 50%; position: absolute; top: 228px; z-index: 2; text-align: center; line-height: 44px; opacity: 0; transition: all 0.5s; &.prev { left: 20px; } &.next { right: 20px; } } } &:hover { .carousel-btn { opacity: 1; } } } </style>
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!