前端大白 -- 小程序之自行封装轮播图组件

本文是前端新手关于小程序封装轮播图组件的教程,详细介绍了HTML、JS和CSS代码实现,并提供父组件调用示例,适合初学者学习和实践。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

小程序之自行封装轮播图组件

案例展示:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

先上代码:

子组件HTML部分:

<view class="ul">
			<view :class="direction == 'column' ? 'columnLi' : 'li'" id="liId" :animation="animate">
				<image id="imageId" @touchend="touchEnd" @touchmove="touchMove" @touchstart="touchStart" :src="item" mode="aspectFill"
				 v-for="(item,index) of bannerList" :key="index"></image>
			</view>
			<!-- 点索引 -->
			<view v-if="dotShowOne" :class="direction == 'column' ? 'column' : 'dotShow'">
				<view class="dot" :class="{'activeDot' : dotIndex == index}" v-for="(item,index) of dotList" :key="index"></view>
			</view>
			<!-- 分数索引 -->
			<view class="dotShow" v-if="dotShowtwo">
				{{dotIndex+1}} / {{length}}
			</view>
		</view>

上面代码中,可以根据自己的想要的轮播方向,进行轮播,只要传入参数direction : ‘column’ / ‘row’;
也可以选择索引点的样式.

子组件JS部分:

<script>
	export default {
		props: {
			bannerList: {
				type: Array,
				default () {
					return []
				}
			},
			// 逗点索引方向  默认是row  可选column
			direction: {
				type: String,
				default: 'row'
			},
			// 样式选择
			dotShow:{
				type: Boolean,
				default: true
			}
		},
		data() {
			return {
				// 开始X坐标
				startX: 0,
				// 开始的Y坐标
				startY: 0,
				// 结束X坐标
				endX: 0,
				// 结束的Y坐标
				endY: 0,
				// 当前image索引
				currentIndex: 0,
				// 自动轮播定时器
				timer: '',
				// 当前图片的width
				imageWidth: 0,
				// 当前图片的高度
				imageHeight: 0,
				// 运行的距离
				imageLeft: 0,
				imageTop: 0,
				// 动画
				animate: {},
				// 索引点
				dotList: [],
				// 长度
				length: 0,
				// 索引点下标
				dotIndex: 0,
				// 新的bannerList
				newBannerList: this.bannerList
			}
		},
		//第一次加载
		created() {
			this.length = this.bannerList.length
			this.dotList = this.length
			this.init()

		},
		//页面显示
		onShow() {},
		//方法
		methods: {
			// 初始方法
			init() {
				this.newBannerList.push(this.bannerList[0])
				this.newBannerList.push(this.bannerList[this.length - 1])
				this.timer = setInterval(this.slide, 3000);
			},
			// 动画方法
			animationFn(duration, currentIndex) {
				var animation = uni.createAnimation({
					duration: duration,
					timingFunction: 'ease',
					delay: 0
				});
				if (this.direction == 'column') {
					this.imageTop = -this.imageHeight * (this.currentIndex)
					animation.translateY(this.imageTop).step();
					this.animate = animation.export();
				} else {
					this.imageLeft = -this.imageWidth * (this.currentIndex);
					// console.log('this.imageLeft ==>'+this.currentIndex,this.imageLeft)
					animation.translateX(this.imageLeft).step();
					this.animate = animation.export();
				}


			},
			// 实现自动轮播方法
			slide() {

				const query = uni.createSelectorQuery().in(this);
				query.select('#imageId').boundingClientRect((res) => {
					this.imageWidth = res.width;
					this.imageHeight = res.height;
				}).exec();

				this.currentIndex++;
				this.dotIndex = this.currentIndex;
				// console.log(this.currentIndex)
				if (this.currentIndex === parseInt(this.newBannerList.length - 2)) {
					this.dotIndex = 0;
				};
				if (this.currentIndex === parseInt(this.newBannerList.length - 1)) {
					this.dotIndex = 0;
					this.currentIndex = 0;
					const queryli = uni.createSelectorQuery().in(this);
					queryli.select('#liId').boundingClientRect((res) => {
						res.left = this.imageWidth
					}).exec();

					this.animationFn(5, this.currentIndex)
				} else {
					this.animationFn(1000, this.currentIndex)
				}

			},

			touchStart(e) {

				this.startX = e.touches[0].pageX;
				this.startY = e.touches[0].pageY;
				clearInterval(this.timer)
			},
			touchMove(e) {

				this.endX = e.touches[0].pageX;
				this.endY = e.touches[0].pageY;
			},
			touchEnd(e) {

				if (this.startX - this.endX > 0 || this.startY - this.endY > 0) {
					this.currentIndex++;
					this.dotIndex = this.currentIndex
					this.animationFn(1000, this.currentIndex)
					console.log(this.currentIndex)
					if (this.currentIndex === parseInt(this.newBannerList.length - 2)) {
						this.dotIndex = 0
					}
					if (this.currentIndex === parseInt(this.newBannerList.length - 1)) {
						this.dotIndex = 0
						this.currentIndex = 0;
						this.animationFn(0, this.currentIndex)
					}


				} else {
					--this.currentIndex;
					this.dotIndex = this.currentIndex
					console.log(this.currentIndex)
					this.animationFn(1000, this.currentIndex)

					if (this.currentIndex < 0) {
						this.currentIndex = parseInt(this.newBannerList.length - 2);
						this.dotIndex = 0
						this.animationFn(0, this.currentIndex)
					}

				}
				clearInterval(this.timer)
				this.timer = setInterval(this.slide, 3000)
			},
		},
		//页面隐藏
		onHide() {},
		//页面卸载
		onUnload() {},
		//页面下来刷新
		onPullDownRefresh() {},
		//页面上拉触底
		onReachBottom() {},
		//用户点击分享
		onShareAppMessage(e) {}
	}
</script>

本人是通过uni.createAnimation()来实现动画效果的.

子组件CSS部分:

<style lang="scss" scoped>
	@import "@/style/mixin.scss";

	.ul {
		width: 100%;
		min-height: 667upx;
		overflow: hidden;
		position: relative;
		left: 0;
		top: 0;

		.columnLi {
			position: absolute;
			top: 0;
			left: 0;
			width: 100%;

			>image {

				flex-shrink: 0;
				width: 100%;
				min-height: 667upx;
			}
		}

		.li {
			display: flex;
			position: absolute;
			top: 0;
			left: 0;
			width: 100%;

			// height: 100%;
			>image {

				flex-shrink: 0;
				width: 100%;
				min-height: 667upx;
			}
		}

		.dotShow {
			display: flex;
			justify-content: center;
			position: absolute;
			bottom: 20upx;
			left: 0;
			right: 0;
			color: #fff;

			.dot {
				width: 20upx;
				height: 20upx;
				margin: 0 10upx;
				border-radius: 50%;
				background-color: aliceblue;
			}

			.activeDot {
				background-color: brown;
			}
		}

		.column {
			display: flex;
			flex-direction: column;
			align-items: center;
			justify-content: center;
			position: absolute;
			top: 50%;
			bottom: 0upx;
			right: 0;
			margin-top: -332upx;
			width: 50upx;

			.dot {
				width: 20upx;
				height: 20upx;
				margin: 10upx;
				border-radius: 50%;
				background-color: aliceblue;
			}

			.activeDot {
				background-color: brown;
			}
		}
	}
</style>

父组件的调用 :

<template>
	<view>
		<my-slide-show :bannerList="bannerList" direction="row" :dotShow="true"></my-slide-show>
	</view>
</template>

<script>
	import mySlideShow from '@/components/common/mySlideShow.vue';
	export default{
		components:{
			mySlideShow
		},
		data(){
			return{
				bannerList: [
					"http://pic51.nipic.com/file/20141025/8649940_220505558734_2.jpg",
					"http://img.redocn.com/sheying/20140731/qinghaihuyuanjing_2820969.jpg",
					"http://photocdn.sohu.com/20111207/Img328215620.jpg",
					"http://pic51.nipic.com/file/20141025/8649940_220505558734_2.jpg",
					"http://img.redocn.com/sheying/20140731/qinghaihuyuanjing_2820969.jpg",
				],
			}
		}
	}
</script>

<style>
</style>

作为一个前端大白,因为想自己学习封装一下小程序的swiper,便自己写了一个插件.有兴趣的大白们,可以拿去练手. – 大宝

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值