场景:近期在做页面的时候,公司有这么一个需求:要做一个看板,然后这个看板里面有很多列表,列表自动滚动,表格内的内容自动滚动。接到这种需求后,第一时间想的是找对应的插件去完成,最后发现都不能满足,这令我很脑壳疼,最后决定自己做
过程就不说了,直接上hooks,有点简陋,哪里需要改进的,希望兄弟姐妹没批评指正。
import { ref } from 'vue'
const useScroll = (elRef: any) => {
const el = elRef.$el
const stopScroll = () => {
clearInterval(timer.value)
}
const timer = ref<any>(null)
const currentTop = ref(0)
const startScroll = () => {
stopScroll()
timer.value = setInterval(() => {
try {
currentTop.value += 0.5
// 获取内容器的高度
const clientHeight = el.querySelector(
'.el-scrollbar__view'
).clientHeight
const height = el.clientHeight
const pointHeight = clientHeight - height
if (pointHeight <= currentTop.value) {
currentTop.value = 0
}
elRef.setScrollTop(currentTop.value)
} catch (error) {
// console.log(error)
}
}, 20)
}
// 当鼠标移入的时候停止滚动
el.addEventListener('mouseover', () => {
stopScroll()
})
// 当鼠标移出的时候继续滚动
el.addEventListener('mouseleave', () => {
// 当鼠标在元素中滚动之后,计算出最后高度再从最终高度开始
currentTop.value = parseInt(
el.querySelector('.el-scrollbar__wrap').scrollTop
)
startScroll()
})
startScroll()
return {
stopScroll,
startScroll,
}
}
export default useScroll
食用方式:
<template>
<el-table
ref="elTableRef"
:data="tableData"
:style="width"
:height="height"
:border="true"
>
<!-- code -->
</el-table>
</template>
<script setup lang="tsx">
import { ref, onMounted } from 'vue'
import useScroll from '@/hooks/useScroll'
const elTableRef = ref<any>({})
onMounted(() => {
useScroll(elTableRef.value)
})
</script>
这样就可以自己滚动了,顺便说一下也适用于被<el-scrollbar></el-scrollbar>组件包裹的元素,ref挂在当前el-scrollbar组件上即可
<el-scrollbar height="30vh" ref="elScrollbarRef">
<!-- code -->
</el-scrollbar>
使用方式一样。
现在存在的问题:
- 因为element-plus的虚拟滚动不能判断组件内元素的高度,并且end-reached事件现在有bug所以不能做,但是实现的方式也挺简单的,监听它的触底事件,停止或者重新开始滚动。
- 滚动不够丝滑,因为只是简单的滚动动画,所以不够平滑,如果有更好的方案麻烦私聊我。