我将在这个博客中更新各种组件的封装,轮播图,骨架屏,复选框,对话框,面包屑组件...看到就是学到,偷着乐吧。
轮播图封装详解:
注册一个vue文件,在src的components中注册一个Carousel.vue
在vue.use中注册全局组件
import Carousel from '@/components/Carousel/Carousel.vue';
import { App } from 'vue'
export default {
install(app: App) {
app.component('Carousel', Carousel)
}
}
vue.use在main.ts中引入
import UI from '@/components/index'
app.use(UI)
接来下我们就可以在组件中写代码啦!先把样式写出来,这是最难写的,如果样式不会写那就学吧,学无止境!
<script lang="ts" setup name="Carousel">
defineProps()
</script>
<template>
<div class="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">
.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>
在pinia中接收请求到的数据,父组件把值传给子组件,子组件接收(注意写好泛型哦)
在pinia中接收
import { defineStore } from 'pinia'
import request from '@/utils/request'
export default defineStore('category', {
state() {
return {
topCategory: {} as TopCategory,
list:topCategoryList as CategoryItem[]
}
},
actions: {
// 获取分类列表
async getCategoryList(){
// const res = await request.get<{msg: string, result:CategoryItem[]}>('/home/category/head')
const res = await request.get<IApiRes<CategoryItem[]>>('/home/category/head')
console.log(res)
this.list = res.data.result
},
}
父组件给子组件传值
// 父组件给子组件传值
<Carousel :slides="home.bannerList" :autoPlay="true" :duration="2000"/>
子组件接收数据,逻辑渲染
<script lang="ts" setup name="Carousel">
import { BannerItem } from '@/types/data'
import {onBeforeUnmount, onMounted, ref } from 'vue';
// 定义props
const { slides, autoPlay=true, duration=1000 } = 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">
<!-- fade类表示当前图片可见 -->
<li class="carousel-item" :class="{fade: idx === active}" v-for="(item,idx) in slides" :key="item.id">
<RouterLink to="/">
<img
:src="item.imgUrl"
alt=""
/>
</RouterLink>
</li>
</ul>
<a @click="hPrev" href="javascript:;" class="carousel-btn prev"><i class="iconfont icon-angle-left"></i></a>
<a @click="hNext" href="javascript:;" class="carousel-btn next"><i class="iconfont icon-angle-right"></i></a>
<div class="carousel-indicator">
<span
v-for="(item,idx) in slides"
@mouseover="active = idx"
:class="{active: active===idx}"></span>
</div>
</div>
</template>