在Vue3项目中,难免会遇到让列表滚动的需求,下方为封装好的组件,可直接赋值运行(如需特定事件跳特定的高度,需自行修改。Vue2版本的已放上一篇文章)
<template>
<div class="scrollList">
<h2>无缝滚动</h2>
<div @mousemove="testMove" @mouseleave="testMend" >
<div ref="roll" style="height: 110px;overflow: hidden;margin:20px;">
<slot>
<li>测试1</li>
<li>测试2</li>
<li>测试3</li>
<li>测试4</li>
<li>测试5</li>
<li>测试6</li>
<li>测试7</li>
</slot>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import {ref,onBeforeUnmount,onUnmounted,nextTick} from 'vue'
//定时器初始化
let timer = ref<any>(null)
//ref绑定初始化
let roll = ref(null)
//组件销毁前需清除定时器
onBeforeUnmount(()=>{
//清除定时器
clearTimeout(timer.value)
})
//组件销毁后需清除定时器
onUnmounted(()=>{
//清除定时器
clearTimeout(timer.value)
})
//鼠标移入事件
function testMove(){
clearTimeout(timer.value)
}
//鼠标移出事件
function testMend(){
start()
}
//开启定时器方法
function start(){
//清除定时器
clearTimeout(timer.value)
//定时器触发周期,移动速度
let speed = ref(50)
timer.value = setInterval(MarqueeTest, speed.value)
}
function MarqueeTest() {
let test1:any = roll.value
//判断组件是否渲染完成
if (test1.offsetHeight == 0) {
test1 = roll.value
} else {
//如果列表数量过少不进行滚动
if(test1.childNodes.length < 6){
clearTimeout(timer.value)
return;
}
//组件进行滚动
test1.scrollTop += 1
//判断滚动条是否滚动到底部
if (test1.scrollTop == (test1.scrollHeight - test1.clientHeight)) {
//获取组件第一个节点
let a = test1.childNodes[0]
//删除节点
test1.removeChild(a)
//将该节点拼接到组件最后
test1.append(a)
}
}
}
//启动定时器
start()
//用nextTick 的原因是 需要等dom元素加载完毕后 再执行方法
nextTick(()=>{
start()
})
</script>
<style lang="scss" scoped>
.scrollList{
width: 100%;
height: 100%;
h2{
text-align: center;
}
}
</style>
原理:
主要就是通过通过计时器不断的给获取到的容器增加它的自身高度,在与可视高度为0时,将容器内的第一个子元素添加到容器底部,从而达到首尾呼应