封装一个轮播图组件
功能:
1.有上下切换的点击图标,可以实现点击切换上下张
2.底部有小圆点,对应每一张图片,图片切换,小圆点对应切换
3.小圆点可以点击切换,对应的图片也会切换
父组件通过自定义属性传值传递包含图片的数组变量,
子组件通过prorps接收数组,循环渲染数组中的图片
html部分:
<template> <div class="home-banner"> <div class="carousel"> <!-- 轮播图图片部分 --> <ul class="carousel-body"> <li class="carousel-item fade"> <img src="" alt="" /> </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> </div> </template>
css部分
<style scoped lang="less"> .home-banner { width: 1240px; height: 500px; position: absolute; left: 0; top: 0; z-index: 98; background-color: pink; } .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>
1.导入轮播图组件,页面使用组件名便签(此处为局部组件注册,可以注册为全局组件)
2.模拟轮播图数据,对象数组,每个对象有图片数据imageUrl和id
3.通过自定义属性把轮播图数据传递给子组件
<script setup lang='ts'> import Carousel from "@/components/carousel/index.vue" import { ref } from "vue"; const bannerList = ref([ { imageUrl: "1.jpg", id: 1 }, { imageUrl: "2.jpg", id: 2 }, { imageUrl: "3.jpg", id: 3 }, { imageUrl: "4.jpg", id: 4 }, { imageUrl: "5.jpg", id: 5 } ]) </script> <template> <Carousel :slides="bannerList" /> </template> <style scoped> </style>
<script lang="ts" setup name="Carousel"> const { slides } = defineProps<{ slides: [] }>() </script> .....省略 <!-- 轮播图图片 --> <ul class="carousel-body"> <li class="carousel-item " fade v-for="(item, index) in slides" :key="item.id"> <img :src="item.imageUrl" alt="" /> </li> </ul> ......省略 <!-- 底部小圆点 --> <div class="carousel-indicator"> <span v-for="(item, index) in slides" active :key="item.id"></span> </div>
点击上下张图标切换图片:
点击底部小圆点切换图片:
<script lang="ts" setup name="Carousel"> import { ref } from 'vue'; const { slides } = defineProps<{ slides: [] }>() //高亮下标 const active = ref(0) // 上一张下一张 const prev = () => { active.value-- if (active.value < 0) { active.value = slides.length - 1 } } const next = () => { active.value++ if (active.value > slides.length - 1) { active.value = 0 } } </script <template> <div class="carousel" @mouseenter="stop" @mouseleave="start"> <!-- 轮播图图片 --> <ul class="carousel-body"> <li class="carousel-item " :class="{ fade: active === index }" v-for="(item, index) in slides" :key="item.id"> <RouterLink :to="item.hrefUrl"> <img :src="item.imgUrl" alt="" /> </RouterLink> </li> </ul> <a href="javascript:;" rel="external nofollow" rel="external nofollow" rel="external nofollow" class="carousel-btn prev" @click="prev"><i class="iconfont icon-angle-left"></i></a> <a href="javascript:;" rel="external nofollow" rel="external nofollow" rel="external nofollow" class="carousel-btn next" @click="next"><i class="iconfont icon-angle-right"></i></a> <!-- 底部小圆点 --> <div class="carousel-indicator"> <span v-for="(item, index) in slides" @click="active=index" :class="{ active: active === index }" :key="item.id"></span> </div> </div> </template>
封装组件可以通过父子组件传值,插槽传值,实现数据传递
我们需要在图片到达临界时对index进行处理,实现图片首尾衔接
// 上一张下一张 const prev = () => { active.value-- if (active.value < 0) { active.value = slides.length - 1 } } const next = () => { active.value++ if (active.value > slides.length - 1) { active.value = 0 } }
:class="{ active: active === index }"
@click="active=index"