vue3 加 TypeScript 来封装 全局组件 轮播图

二级标题

轮播图-通用轮播图组件
项目中会多次使用到轮播图组件,且轮播图渲染的数据是不一样的。轮播图的基本功能都是一样的,比如图片切换,自动播放等等。因此需要封装一个通用的轮播图组件。

轮播图的基本结构

<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="http://yjy-xiaotuxian-dev.oss-cn-beijing.aliyuncs.com/picture/2021-04-15/1ba86bcc-ae71-42a3-bc3e-37b662f7f07e.jpg"
            alt=""
          />
        </RouterLink>
      </li>
      <li class="carousel-item">
        <RouterLink to="/">
          <img
            src="http://yjy-xiaotuxian-dev.oss-cn-beijing.aliyuncs.com/picture/2021-04-15/1ba86bcc-ae71-42a3-bc3e-37b662f7f07e.jpg"
            alt=""
          />
        </RouterLink>
      </li>
      <li class="carousel-item">
        <RouterLink to="/">
          <img
            src="http://yjy-xiaotuxian-dev.oss-cn-beijing.aliyuncs.com/picture/2021-04-15/1ba86bcc-ae71-42a3-bc3e-37b662f7f07e.jpg"
            alt=""
          />
        </RouterLink>
      </li>
    </ul>
    <a href="javascript:;" class="carousel-btn prev"
      ><i class="iconfont icon-angle-left"></i
    ></a>
    <a href="javascript:;" 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>

逻辑封装

完成轮播图的交互逻辑
● 自动播放,暴露自动轮播属性,设置了就自动轮播
○ 如果有自动播放,鼠标进入离开,暂停,开启
● 指示器切换,上一张,下一张
● 销毁组件,清理定时器
具体代码

<script lang="ts" setup name="XtxCarousel">
import { onBeforeUnmount, onMounted, ref } from "vue";
// duration: 决定切换一张图需要的时间。它就是自动播放的间隔 autoPlay:是否自动播放 
const {duration,autoPlay} = defineProps<{duration:number,autoPlay:boolean}>();
const arr = [
  "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fcdn.micuer.com%2Fimage_temp%2F1c6cd32394529b50aa9e847855221828_1200_1200.png&refer=http%3A%2F%2Fcdn.micuer.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1661180945&t=9426000bbc2d3eec4b1207a8b1777220",
  "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fi0.hdslb.com%2Fbfs%2Farticle%2F8d802d12bc084b60a805e76d241170095a479408.jpg&refer=http%3A%2F%2Fi0.hdslb.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1661180945&t=d72a8ba8e8a78f5d442a7efa821fb2a3",
  "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fpic1.win4000.com%2Fwallpaper%2F2019-12-23%2F5e008399e32fa.jpg&refer=http%3A%2F%2Fpic1.win4000.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1661180945&t=51e0ac7642ecfbe6548aed2a6579aced  ",
  "https://img2.baidu.com/it/u=1912999255,2672254654&fm=253&fmt=auto&app=120&f=JPEG?w=1280&h=800",
  "https://img2.baidu.com/it/u=1884557076,4135193950&fm=253&fmt=auto&app=138&f=JPEG?w=909&h=500"
];

// 初始值 默认那个图片选中
let active = ref(0);
// 左边按钮
const left = () => {
  active.value--;
  // 如果初始值 大于 0 便让初始值 等于 数组的长度减一
  if(active.value < 0) {
    active.value = arr.length-1
  }
};

// 右边按钮
const right = () => {
  active.value++;
  // 如果初始值等于数组的长度变回跳 到 0
  if(active.value===arr.length){
    active.value=0
  }
};

// 销毁组件,清理定时器
onBeforeUnmount(()=>{
  stop()
})

// 自动播放 如果开启了自动播放 则每隔duration 去播放下一张 left()
onMounted(()=>{
  start()
})

let timer = -1
// 开始  // 鼠标离开要继续播放
const start =()=>{
  // 如果是true 就开启定时器
if(autoPlay){
   timer=window.setInterval(()=>{
      right()
    },duration)
  }
}

// 停止 // 鼠标经过要暂停播放 
const stop = ()=>{
  // 清除定时器
clearInterval(timer)
}
</script>

<template>
  <div class="xtx-carousel">
    <ul class="carousel-body" @mouseleave="start()" @mouseenter="stop()">
      <!-- fade 表示当前可见的图片 -->
      <li class="carousel-item" :class="{ fade: active === index }" v-for="(item, index) in arr" :key="index">
        <RouterLink to="/">
          <img :src="item" alt="" />
        </RouterLink>
      </li>
    </ul>
    <a href="javascript:;" @click="left" class="carousel-btn prev"><i class="iconfont icon-angle-left"></i></a>
    <a href="javascript:;" @click="right" class="carousel-btn next"><i class="iconfont icon-angle-right"></i></a>
    <div class="carousel-indicator">
      <span @mouseover="active=index" :class="{active:active===index}" v-for="(item,index) in arr" :key="index"></span>
      <!-- mouseover是鼠标经过 小圆点 高亮 切换图 -->
    </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>

不要忘记全局注册
我这边是在 components 文件下面从新创建一个 index.ts 专门来放 全局注册

// 全局组件注册
import {App} from 'vue'
import XtxCarousel from './XtxCarousel/XtxCarousel.vue'

export default{
  install(app:App){
    app.component('XtxCarousel',XtxCarousel)
  }
}

在 在mian.ts 里面导入挂载

import { createApp } from 'vue'
import App from './App.vue'
// 导入路由
import routers from './ router/index'
// 全局组件
import XtxUI from './components/index'

 
const app = createApp(App)
app.use(routers)
app.use(XtxUI)
app.mount('#app')

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值