Vue:实现一个无线滚动列表的解决方案
文章目录
- 前言
- 一、解决方案
- 1.方案1:
- 实现思路
- 完整实现代码
- 代码解释
- 方案2:方案1的进阶优化
- 1.使用 CSS 动画实现平滑滚动
- 2.添加动态数据更新功能
- 总结
前言
vue 实现 move-box 区域 内容无限向上滚动 效果
<div class="warning-info"><div class="move-box" ref="moveBox"><div class="info-item" v-for="(item, index) in warningInfoList" :key="index"><div class="name">{{ item.name }}</div><div class="time">{{ item.time }}</div></div></div>
</div>
无线滚动(轮播)列表
一、解决方案
1.方案1:
要实现 move-box 区域内容无限向上滚动的效果,我们需要使用 Vue 的生命周期钩子和定时器来控制滚动位置。下面我将为你提供完整的实现方案。
实现思路
- 使用 CSS 设置 move-box 的固定高度和隐藏溢出内容
- 使用 Vue 的 ref 获取 move-box 元素
- 使用 setInterval 创建定时器,定期改变滚动位置
- 当滚动到底部时,重置滚动位置到顶部,形成无限滚动效果
- 在组件销毁时清除定时器,避免内存泄漏
完整实现代码
<template><div class="warning-info"><div class="move-box" ref="moveBox"><div class="info-item" v-for="(item, index) in warningInfoList" :key="index"><div class="name">{{ item.name }}</div><div class="time">{{ item.time }}</div></div></div></div>
</template><script>
export default {name: 'InfiniteScroll',data() {return {warningInfoList: [{ name: '设备1', time: '2023-05-20 10:30:45' },{ name: '设备2', time: '2023-05-20 10:31:22' },{ name: '设备3', time: '2023-05-20 10:32:15' },{ name: '设备4', time: '2023-05-20 10:33:08' },{ name: '设备5', time: '2023-05-20 10:34:30' },{ name: '设备6', time: '2023-05-20 10:35:12' },{ name: '设备7', time: '2023-05-20 10:36:45' },{ name: '设备8', time: '2023-05-20 10:37:22' }],scrollTimer: null,scrollSpeed: 50, // 滚动速度,数值越小滚动越快scrollDistance: 1, // 每次滚动的距离isPaused: false // 是否暂停滚动}},mounted() {this.startScroll();// 鼠标悬停时暂停滚动this.$refs.moveBox.addEventListener('mouseenter', this.pauseScroll);this.$refs.moveBox.addEventListener('mouseleave', this.resumeScroll);},beforeDestroy() {// 组件销毁前清除定时器和事件监听this.stopScroll();if (this.$refs.moveBox) {this.$refs.moveBox.removeEventListener('mouseenter', this.pauseScroll);this.$refs.moveBox.removeEventListener('mouseleave', this.resumeScroll);}},methods: {startScroll() {this.stopScroll(); // 确保没有多个定时器同时运行this.scrollTimer = setInterval(() => {if (!this.isPaused && this.$refs.moveBox) {const moveBox = this.$refs.moveBox;// 如果滚动到底部,重置到顶部if (moveBox.scrollTop >= moveBox.scrollHeight - moveBox.clientHeight) {moveBox.scrollTop = 0;} else {moveBox.scrollTop += this.scrollDistance;}}}, this.scrollSpeed);},stopScroll() {if (this.scrollTimer) {clearInterval(this.scrollTimer);this.scrollTimer = null;}},pauseScroll() {this.isPaused = true;},resumeScroll() {this.isPaused = false;}}
}
</script><style scoped>
.warning-info {width: 100%;height: 300px; /* 可以根据需要调整高度 */border: 1px solid #eee;border-radius: 4px;overflow: hidden;position: relative;
}.move-box {width: 100%;height: 100%;overflow-y: auto; /* 允许垂直滚动 */scrollbar-width: none; /* 隐藏滚动条 - Firefox */-ms-overflow-style: none; /* 隐藏滚动条 - IE/Edge */
}.move-box::-webkit-scrollbar {display: none; /* 隐藏滚动条 - Chrome/Safari/Opera */
}.info-item {padding: 10px 15px;border-bottom: 1px solid #f0f0f0;display: flex;justify-content: space-between;align-items: center;
}.info-item:last-child {border-bottom: none;
}.name {font-weight: bold;width: 30%;
}.time {color: #999;font-size: 0.9em;width: 30%;text-align: right;
}/* 可选:添加滚动动画效果 */
.move-box {scroll-behavior: smooth;
}
</style>
代码解释
数据结构:
warningInfoList:存储要显示的警告信息列表
scrollTimer:存储定时器的引用
scrollSpeed:控制滚动速度
scrollDistance:每次滚动的像素距离
isPaused:控制滚动是否暂停
生命周期钩子:
mounted:组件挂载后启动滚动,并添加鼠标悬停事件监听
beforeDestroy:组件销毁前清除定时器和事件监听,防止内存泄漏
方法:
startScroll:启动滚动定时器
stopScroll:停止滚动定时器
pauseScroll:暂停滚动
resumeScroll:恢复滚动
CSS 样式:
设置 .warning-info 和 .move-box 的尺寸和溢出处理
隐藏滚动条,使滚动效果更自然
设置 .info-item 的布局和样式
方案2:方案1的进阶优化
如果你想要更平滑的滚动效果或者更复杂的功能,可以考虑以下优化:
1.使用 CSS 动画实现平滑滚动
<template><div class="warning-info"><div class="move-box" ref="moveBox"><div class="content-wrapper" ref="contentWrapper"><div class="info-item" v-for="(item, index) in warningInfoList" :key="index"><div class="name">{{ item.name }}</div><div class="time">{{ item.time }}</div></div><!-- 复制一份内容以实现无缝滚动 --><div class="info-item" v-for="(item, index) in warningInfoList" :key="'copy-'+index"><div class="name">{{ item.name }}</div><div class="time">{{ item.time }}</div></div></div></div></div>
</template><script>
export default {name: 'SmoothInfiniteScroll',data() {return {warningInfoList: [// 数据同上],animationDuration: 20, // 动画持续时间(秒)isPaused: false}},mounted() {this.startAnimation();this.$refs.moveBox.addEventListener('mouseenter', this.pauseAnimation);this.$refs.moveBox.addEventListener('mouseleave', this.resumeAnimation);},beforeDestroy() {this.stopAnimation();if (this.$refs.moveBox) {this.$refs.moveBox.removeEventListener('mouseenter', this.pauseAnimation);this.$refs.moveBox.removeEventListener('mouseleave', this.resumeAnimation);}},methods: {startAnimation() {const contentWrapper = this.$refs.contentWrapper;if (contentWrapper) {// 计算内容高度的一半(因为我们复制了一份内容)const halfHeight = contentWrapper.scrollHeight / 2;// 设置动画contentWrapper.style.animation = `scroll ${this.animationDuration}s linear infinite`;// 定义CSS动画const style = document.createElement('style');style.innerHTML = `@keyframes scroll {0% { transform: translateY(0); }100% { transform: translateY(-${halfHeight}px); }}`;document.head.appendChild(style);}},stopAnimation() {const contentWrapper = this.$refs.contentWrapper;if (contentWrapper) {contentWrapper.style.animationPlayState = 'paused';}},pauseAnimation() {const contentWrapper = this.$refs.contentWrapper;if (contentWrapper) {contentWrapper.style.animationPlayState = 'paused';}},resumeAnimation() {const contentWrapper = this.$refs.contentWrapper;if (contentWrapper) {contentWrapper.style.animationPlayState = 'running';}}}
}
</script><style scoped>
.warning-info {width: 100%;height: 300px;border: 1px solid #eee;border-radius: 4px;overflow: hidden;position: relative;
}.move-box {width: 100%;height: 100%;overflow: hidden;
}.content-wrapper {width: 100%;
}.info-item {padding: 10px 15px;border-bottom: 1px solid #f0f0f0;display: flex;justify-content: space-between;align-items: center;
}.name, .time {/* 样式同上 */
}
</style>
2.添加动态数据更新功能
<template><div class="warning-info"><div class="move-box" ref="moveBox"><div class="info-item" v-for="(item, index) in displayList" :key="index"><div class="name">{{ item.name }}</div><div class="time">{{ item.time }}</div></div></div></div>
</template><script>
export default {name: 'DynamicInfiniteScroll',data() {return {warningInfoList: [// 初始数据],displayList: [], // 实际显示的列表scrollTimer: null,scrollSpeed: 50,scrollDistance: 1,isPaused: false,maxItems: 20 // 最大显示项目数}},created() {// 初始化显示列表this.updateDisplayList();// 模拟动态数据更新this.startDataUpdate();},mounted() {this.startScroll();this.$refs.moveBox.addEventListener('mouseenter', this.pauseScroll);this.$refs.moveBox.addEventListener('mouseleave', this.resumeScroll);},beforeDestroy() {this.stopScroll();this.stopDataUpdate();if (this.$refs.moveBox) {this.$refs.moveBox.removeEventListener('mouseenter', this.pauseScroll);this.$refs.moveBox.removeEventListener('mouseleave', this.resumeScroll);}},methods: {startScroll() {this.stopScroll();this.scrollTimer = setInterval(() => {if (!this.isPaused && this.$refs.moveBox) {const moveBox = this.$refs.moveBox;if (moveBox.scrollTop >= moveBox.scrollHeight - moveBox.clientHeight) {moveBox.scrollTop = 0;} else {moveBox.scrollTop += this.scrollDistance;}}}, this.scrollSpeed);},stopScroll() {if (this.scrollTimer) {clearInterval(this.scrollTimer);this.scrollTimer = null;}},pauseScroll() {this.isPaused = true;},resumeScroll() {this.isPaused = false;},startDataUpdate() {// 每30秒添加一条新数据this.dataUpdateTimer = setInterval(() => {const newIndex = this.warningInfoList.length + 1;const newItem = {name: `设备${newIndex}`,time: new Date().toLocaleString()};this.warningInfoList.push(newItem);this.updateDisplayList();}, 30000);},stopDataUpdate() {if (this.dataUpdateTimer) {clearInterval(this.dataUpdateTimer);this.dataUpdateTimer = null;}},updateDisplayList() {// 只保留最新的maxItems个项目if (this.warningInfoList.length > this.maxItems) {this.warningInfoList = this.warningInfoList.slice(-this.maxItems);}this.displayList = [...this.warningInfoList];}}
}
</script><style scoped>
/* 样式同上 */
</style>
总结
以上提供了三种实现无限向上滚动效果的方法:
- 基础实现:使用定时器和 scrollTop 属性控制滚动,简单直接。
- 平滑滚动:使用 CSS 动画实现更平滑的滚动效果,通过复制内容实现无缝滚动。
- 动态数据:添加了动态更新数据的功能,适合实时数据展示场景。
根据你的具体需求,可以选择最适合的方案。基础实现适用于简单场景,平滑滚动提供更好的用户体验,而动态数据实现则适合需要实时更新数据的应用。