2023年4月1日

vue-scrollList垂直滚动列表组件封装

作者 admin

前段时间做了一个web小程序项目,业务上有垂直滚动列表需求,所以咱就开始动手拆分-封装。

父组件:

<!-- 拼团content -->
            <div v-if="data.activityGroup">
                <div class="bl-group-bg">
                    <p class="bl-group-people">{{data.assest_data.length}}人在拼单 可直接参与</p>
                    <div class="bl-group-wrap">
                        <Scroll :id="'service'">
                            <template>
                                <div v-for="(item,index) in data.assest_data" :key="index">
                                    <div class="group-left">
                                        <image class="user-head" :src="item.headImg"></image>
                                        <p class="user-name">{{item.name}}</p>
                                    </div>
                                    <div class="group-right">
                                        <div class="group-state">
                                            <p class="order-people">还差<span class="people-num">{{item.lack}}</span>人
                                            </p>
                                            <p class="order-time">
                                                <!-- <span class="time-text">{{ timeout != 0 ? `剩余${timeout}`: `本次活动已结束`}}</span> -->
                                                <span class="time-text">{{ timeout != 0 && timeoutList[index] ? `剩余${timeoutList[index]}`: `本次活动已结束`}}</span>
                                            <!--    <countDown :endTime="item.endTime" :endText="item.endText"
                                                    class="time-text" :end-tip="'scroll'" /> -->
                                            </p>
                                        </div>
                                        <div class="go-join-btn" v-if="timeout != 0 && timeoutList[index]">
                                            <p class="go-join-text" @click="joinBuying(item,index)">去拼单</p>
                                        </div>
                                    </div>
                                </div>
                            </template>
                        </Scroll>
                    </div>
                </div>
            </div>


<script>

import Scroll from "../components/scrollList/scrollList.vue"

export default {
		components: {
			Scroll,
		},


data: {


					assest_data: [{
							headImg: '../../../static/images/groupBuyingDetail/bl_share_icon5.png', //头像
							name: '微信用户', //名字
							lack: 1, //缺少多少人可以拼单
							endTime: new Date("2023/03/27 01:00:00").getTime() / 1000 + ' ',
							endText: '',
						},
						{
							headImg: '../../../static/images/groupBuyingDetail/bl_service_icon.png',
							name: '微***',
							lack: 2, //缺少多少人
							endTime: new Date("2023/04/16 12:00:00").getTime() / 1000 + ' ',
							endText: '',
						}, 
						{
							headImg: '../../../static/images/groupBuyingDetail/bl_home_icon.png',
							name: '微***',
							lack: 3, //缺少多少人
							endTime: new Date("2023/04/15 06:00:00").getTime() / 1000 + ' ',
							endText: '',
						}, 
						// {
						// 	headImg: '../../../static/images/groupBuyingDetail/bl_share_icon5.png',
						// 	name: '微***',
						// 	lack: 4, //缺少多少人
						// 	endTime: new Date("2023/04/14 09:00:00").getTime() / 1000 + ' ',
						// 	endText: '',
						// }
					],
}

</script>

子组件:

<template>
	<!-- 设定一个容器,给一组id和高度当你使用这个组件。如果你想改变滚动条的样式,只改变.scrollContainer的风格在你的页面。-->
	<div class="scrollContainer" :id="id" @mouseenter="monseenter" @mouseleave="mouseleave">
		<slot></slot>
	</div>
</template>

<script>
	export default {
		name: 'ScrollList',
		props: {
			id: String
		},
		data() {
			return {
				timer: null
			};
		},
		methods: {
			init() {
				this.setTimer();
				// this.$once代表只执行一次。如果组件是在keep-alive中包裹,则需要更换函数
				// 被keep-alive包裹住的组件有两个生命周期函数:activated和deactivated
				this.$once('hook:beforeDestroy', () => {
					this.removeTimer();
				});
			},
			removeTimer() {
				if (this.timer) {
					clearInterval(this.timer);
					this.timer = null;
				}
			},
			setTimer() {
				this.removeTimer();
				// 初始化容器尺寸
				let scrollHeight = document.getElementById(this.id).scrollHeight;
				let clientHeight = document.getElementById(this.id).clientHeight;
				let heightDifference = scrollHeight - clientHeight;
				// 开启滚动				
				if (heightDifference != 0) {
					this.timer = setInterval(() => {
						//像素高度 : 包括 el 和 填充 只读
						let scrollHeight = document.getElementById(this.id).scrollHeight;
						// 可见区域高度:包括el和填充只读
						let clientHeight = document.getElementById(this.id).clientHeight;
						let heightDifference = scrollHeight - clientHeight;
						// 滚动高度:可读和可写的
						document.getElementById(this.id).scrollTop++;
						// 当滚动到顶部
						if (document.getElementById(this.id).scrollTop >= heightDifference - 1) {
							this.removeTimer();
							// 让它回到原始位置后一秒
							setTimeout(() => {
								let id = document.getElementById(this.id)
								if (id) {
									document.getElementById(this.id).scrollTop = 0;
									this.setTimer();
								}
							}, 1000);
						}
					}, 44);
				}
			},
			monseenter() {
				this.removeTimer();
			},
			mouseleave() {
				this.setTimer();
			}
		},
		mounted() {
			this.init();
		}
	};
</script>

<style lang="scss" scoped>
	// .scrollContainer::-webkit-scrollbar {
	//     width: 4px;
	//     background: aliceblue;
	// }
	.scrollContainer::-webkit-scrollbar-thumb {
		background: palevioletred;
		border-radius: 5px;
	}

	.scrollContainer {
		height: 100%;
		overflow: scroll;
		overflow-x: hidden;
		overflow-y: hidden;
	}

	// 兼容IE
	// .scrollContainer {
	//     /*三角箭头的颜色*/
	//     scrollbar-arrow-color: #fff;
	//     /*滚动条滑块按钮的颜色*/
	//     scrollbar-face-color: #0099dd;
	//     /*滚动条整体颜色*/
	//     scrollbar-highlight-color: #0099dd;
	//     /*滚动条阴影*/
	//     scrollbar-shadow-color: #0099dd;
	//     /*滚动条轨道颜色*/
	//     scrollbar-track-color: #0066ff;
	//     /*滚动条3d亮色阴影边框的外观颜色——左边和上边的阴影色*/
	//     scrollbar-3dlight-color: #0099dd;
	//     /*滚动条3d暗色阴影边框的外观颜色——右边和下边的阴影色*/
	//     scrollbar-darkshadow-color: #0099dd;
	//     /*滚动条基准颜色*/
	//     scrollbar-base-color: #0099dd;
	// }
</style>

结束