要在Vue 2中实现具有可控滚动速度、鼠标移入停止滚动和加载更多数据功能的自动滚动列表指令,可以使用自定义指令和组件结合的方式
首先确定要实现的需求点清单。这里要实现的需求点有:
- 使用指令的方式来实现。
- 可控制滚动速度。
- 可设置鼠标移入后停止滚动。
- 可以加载更多数据。
- 支持循环滚动。
<template>
<div>
<ul v-auto-scroll="scrollOptions">
<li v-for="(item, index) in items" :key="item.id">
{{ item.name }}
<span v-if="index === items.length - 1" ref="lastItem"></span>
</li>
</ul>
<button @click="loadMore">加载更多</button>
</div>
</template>
<script>
export default {
data() {
return {
items: [
{ id: 1, name: 'Item 1' },
{ id: 2, name: 'Item 2' },
{ id: 3, name: 'Item 3' },
// 添加更多项...
],
scrollOptions: {
speed: 2, // 滚动速度(每毫秒滚动的像素数)
pauseOnHover: true, // 鼠标移入停止滚动
loadMoreThreshold: 200, // 距离底部多少像素时加载更多数据
loop: true // 循环滚动
}
};
},
directives: {
'auto-scroll': {
inserted(el, binding) {
const options = binding.value;
let timer = null;
let scrollHeight = el.scrollHeight;
let clientHeight = el.clientHeight;
let loadMoreThreshold = options.loadMoreThreshold;
let isScrolling = false;
function startScroll() {
el.scrollTop += options.speed;
if (el.scrollTop >= scrollHeight - clientHeight - loadMoreThreshold) {
clearTimeout(timer);
if (options.loop) {
resetScroll();
} else {
loadMore();
}
} else {
timer = setTimeout(startScroll, 1);
}
}
function resetScroll() {
el.scrollTop = 0;
timer = setTimeout(startScroll, 1000);
}
function loadMore() {
// 模拟加载更多数据的操作
setTimeout(() => {
const newItems = [
{ id: 4, name: 'Item 4' },
{ id: 5, name: 'Item 5' },
// 添加更多项...
];
this.items = this.items.concat(newItems);
scrollHeight = el.scrollHeight;
}, 500);
}
el.addEventListener('mouseenter', () => {
if (options.pauseOnHover) {
clearTimeout(timer);
isScrolling = false;
}
});
el.addEventListener('mouseleave', () => {
if (options.pauseOnHover && !isScrolling) {
timer = setTimeout(startScroll, 1000);
}
});
timer = setTimeout(startScroll, 1000);
isScrolling = true;
this.$nextTick(() => {
const lastItem = el.querySelector('[ref="lastItem"]');
if (lastItem) {
lastItem.addEventListener('transitionend', () => {
isScrolling = true;
timer = setTimeout(startScroll, 1);
});
}
});
}
}
},
methods: {
loadMore() {
// 手动加载更多数据
loadMore();
}
}
};
</script>
在上述示例中,我们添加了一个名为loop
的选项到scrollOptions
中,并将其设为true
以启用循环滚动功能。
在指令的逻辑中,当滚动到列表底部时,如果循环滚动功能被启用,则会调用resetScroll
函数,将滚动位置重置为列表顶部,并重新开始滚动。如果循环滚动功能未启用,则会触发加载更多数据的操作。
为了正确处理循环滚动时的过渡效果,我们使用$nextTick
在列表渲染完成后获取最后一个项的元素,并在其过渡结束后重新开始滚动。