当前位置:

Vue3 组件封装vue3 轮播图组件封装

访客 2024-04-23 848 0

轮播图功能-获取数据

目标:基于pinia获取轮播图数据

核心代码:

(1)在types/data.d.ts文件中定义轮播图数据的类型声明

//所有接口的通用类型exporttypeApiRes<T>={code:string,msg:string,result:T}//轮播图类型exporttypeBannerItem={hrefUrl:stringid:stringimgUrl:stringtype:string}

(2)在store/home.ts文件中封装接口,用于获取轮播图数据

import{ApiRes,BannerItem}from'@/types/data'importrequestfrom'@/utils/request'import{defineStore}from'pinia'exportdefaultdefineStore('home',{state:()=>({bannerList:[]asBannerItem[],}),actions:{asyncgetBannerList(){const{data:res}=awaitrequest.get<ApiRes<BannerItem[]>>('/home/banner')this.bannerList=res.result},},})

(3)在store/index.ts中导入

importuseCategoryStorefrom'./modules/category'importuseHomeStorefrom'./modules/home'exportdefaultfunctionuseStore(){return{category:useCategoryStore(),home:useHomeStore(),}}

(4)通过开发者工具查看数据

<scriptlang="ts"setup>importuseStorefrom'@/store'const{home}=useStore()home.getBannerList()</script>

轮播图-通用轮播图组件

项目中会多次使用到轮播图组件,但是轮播图渲染的数据是不一样的。

但是轮播图的基本功能都是一样的,比如图片切换,自动播放等等。

因此需要封装一个通用的轮播图组件。

(1)通用轮播图的基本结构src/components/carousel/index.vue

fade类:用于控制图片的显示和隐藏

active类:用于控制小圆点高亮

<scriptlang="ts"setupname="Carousel">defineProps()</script><template><divclass="carousel"><ulclass="carousel-body"><liclass="carousel-itemfade"><RouterLinkto="/"><imgsrc="http://yjy-xiaotuxian-dev.oss-cn-beijing.aliyuncs.com/picture/2021-04-15/1ba86bcc-ae71-42a3-bc3e-37b662f7f07e.jpg"alt=""/></RouterLink></li><liclass="carousel-item"><RouterLinkto="/"><imgsrc="http://yjy-xiaotuxian-dev.oss-cn-beijing.aliyuncs.com/picture/2021-04-15/1ba86bcc-ae71-42a3-bc3e-37b662f7f07e.jpg"alt=""/></RouterLink></li><liclass="carousel-item"><RouterLinkto="/"><imgsrc="http://yjy-xiaotuxian-dev.oss-cn-beijing.aliyuncs.com/picture/2021-04-15/1ba86bcc-ae71-42a3-bc3e-37b662f7f07e.jpg"alt=""/></RouterLink></li></ul><ahref="javascript:;"class="carousel-btnprev"><iclass="iconfonticon-angle-left"></i></a><ahref="javascript:;"class="carousel-btnnext"><iclass="iconfonticon-angle-right"></i></a><divclass="carousel-indicator"><spanclass="active"></span><span></span><span></span><span></span><span></span></div></div></template><stylescopedlang="less">.xtxcarousel{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:opacity0.5slinear;&.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:all0.5s;&.prev{left:20px;}&.next{right:20px;}}}&:hover{.carousel-btn{opacity:1;}}}</style>

(2)全局注册通用轮播图src/components/index.ts

importtype{App}from'vue'importskelectonfrom'./skeleton/index.vue'importCarouselfrom'./carousel/index.vue'exportdefault{install(app:App){app.component(skelecton.name,skelecton)app.component(Carousel.name,Carousel)},}

(3)在广告组件中使用src/views/home/components/home-banner.vue

<template><divclass="home-banner"><!--轮播图--><Carousel></XtxCarousel></div></template>

(4)覆盖样式,控制箭头和小圆点的位置src/views/home/components/home-banner.vue

:deep(.carousel-btn.prev){left:270px!important;}:deep(.carousel-indicator){padding-left:250px;}

(5)查看效果

轮播图-数据渲染

目的

home-banner组件把数据传递给Carousel组件进行渲染

(1)父传子的方式将数据传给通用轮播图组件src/views/home/components/home-banner.vue

<Carousel:slides="home.bannerList"></Carousel>

(2)子组件接收数据src/components/carousel/index.vue

了解写法:如果通过js的方法定义类型,需要单独引入PropType进行编写

<scriptlang="ts"setupname="Carousel">import{BannerItem}from'@/types/data'//import{PropType}from'vue'//defineProps({//slides:{//type:ArrayasPropType<BannerItem[]>,//required:true,//},//})defineProps<{slides:BannerItem[]}>()</script>

(3)渲染轮播图数据src/components/carousel/index.vue

<template><divclass="carousel"><ulclass="carousel-body"><liclass="carousel-itemfade"v-for="iteminslides":key="item.id"><RouterLink:to="item.hrefUrl"><img:src="item.imgUrl"alt=""/></RouterLink></li></ul><ahref="javascript:;"class="carousel-btnprev"><iclass="iconfonticon-angle-left"></i></a><ahref="javascript:;"class="carousel-btnnext"><iclass="iconfonticon-angle-right"></i></a><divclass="carousel-indicator"><spanv-for="iteminslides":key="item.id"class="active"></span></div></div></template>

(4)控制高亮的下标

<scriptlang="ts"setupname="Carousel">constactive=ref(0)</script>

(5)高亮渲染

  1. 添加的fade的图片才会展示,所以根据当前索引号进行判断,索引号等于active的才进行展示
  2. 添加了active类名的小圆点才会高亮,高亮逻辑跟图片一致
<template><divclass="carousel"><ulclass="carousel-body"><liclass="carousel-item":class="{fade:active===index}"v-for="(item,index)inslides":key="item.id"><RouterLink:to="item.hrefUrl"><img:src="item.imgUrl"alt=""/></RouterLink></li></ul><ahref="javascript:;"class="carousel-btnprev"><iclass="iconfonticon-angle-left"></i></a><ahref="javascript:;"class="carousel-btnnext"><iclass="iconfonticon-angle-right"></i></a><divclass="carousel-indicator"><spanv-for="(item,index)inslides":key="item.id":class="{active:active===index}"></span></div></div></template>

轮播图-逻辑封装

实现需求:

  1. 轮播图里面的图片需要从父组件传入(因为轮播组件可以复用)
  2. 父组件需要控制轮播图的是否自动播放、动画时间(处理默认值逻辑)
    • 是否自动播放和动画时间都是需要默认值的(如果不传就可以使用轮播组件自己提供的默认值)
  3. 播放逻辑
    1. 点击小圆点可以切换图片
    2. 点击prev和next按钮可以播放指定图片(根据图片个数判断播放的循环)
    3. 如果父组件配置了自动播放,则需要定时播放图片
    4. 鼠标进入轮播图,暂停轮播
    5. 鼠标离开轮播图,继续轮播
    6. 注意点:组件卸载的时候需要清除定时轮播效果(不然组件重新加载的时候会导致多个定时器开启)

(1)父组件传值给轮播图src/views/home/components/home-banner.vue

<template><divclass="home-banner"><!--轮播图--><Carousel:slides="slides"autoPlay:duration="3000"></XtxCarousel></div></template>

(2)props接收src/components/Carousel.vue

<scriptlang="ts"setupname="Carousel">import{BannerItem}from'@/types/data'import{ref,PropType}from'vue'defineProps({slides:{type:ArrayasPropType<BannerItem[]>,required:true,},autoPlay:{type:Boolean,default:false,},duration:{type:Number,default:3000,},})constactive=ref(0)</script>

(3)轮播图的播放逻辑

<scriptlang="ts"setupname="Carousel">import{BannerItem}from'@/types/data'import{onMounted,onUnmounted,PropType,ref}from'vue'//import{PropType}from'vue'constprops=defineProps({slides:{type:ArrayasPropType<BannerItem[]>,required:true,},duration:{type:Number,default:3000,},autoPlay:{type:Boolean,default:false,},})//constprops=defineProps<{//slides:BannerItem[]//}>()//控制高亮constactive=ref(0)constprev=()=>{if(active.value<=0){active.value=props.slides.length-1}else{active.value--}}constnext=()=>{if(active.value>=props.slides.length-1){active.value=0}else{active.value}}constplay=()=>{//如果没有自动播放if(!props.autoPlay)return//在ts中,使用定时器,window.setIntervaltimer=window.setInterval(()=>{next()},props.duration)}conststop=()=>{clearInterval(timer)}lettimer=-1//自动播放onMounted(()=>{play()})onUnmounted(()=>{stop()})</script>

(4)鼠标进入和离开操作

<divclass="carousel"@mouseenter="stop"@mouseleave="play">

(5)鼠标经过小圆点切换

<spanv-for="(item,index)inslides":key="item.id":class="{active:active===index}"@mouseenter="active=index"></span>

(6)点击左右箭头切换

constprev=()=>{if(active.value===0){active.value=props.slides.length-1}else{active.value--}}constnext=()=>{if(active.value===props.slides.length-1){active.value=0}else{active.value}}//注册事件<ahref="javascript:;"class="carousel-btnprev"@click="prev"><iclass="iconfonticon-angle-left"></i></a><ahref="javascript:;"class="carousel-btnnext"@click="next"><iclass="iconfonticon-angle-right"></i></a>vascriptconstprev=()=>{if(active.value===0){active.value=props.slides.length-1}else{active.value--}}constnext=()=>{if(active.value===props.slides.length-1){active.value=0}else{active.value}}//注册事件<ahref="javascript:;"class="carousel-btnprev"@click="prev"><iclass="iconfonticon-angle-left"></i></a><ahref="javascript:;"class="carousel-btnnext"@click="next"><iclass="iconfonticon-angle-right"></i></a>

发表评论

  • 评论列表
还没有人评论,快来抢沙发吧~