原创 飞天猫猫头 2025-06-11 08:30 重庆
点击关注公众号,技术干货及时达!
前言
❝本文开发的工具,是vue3 element-plus ui库专用的,需要对vue3指令概念有一定的了解
❞
最近开发的项目中,需要对项目中大量的列表实现轮播效果,经过一番折腾.最终决定不使用第三方插件,手搓一个滚动指令.
效果展示
实现思路
第一步先确定功能
列表自动滚动
鼠标移入停止滚动
鼠标移出继续滚动
滚轮滚动完成,还可以继续在当前位置滚动
元素少于一定条数时,不滚动
「滚动思路」
el-table
的结构可以发现el-scrollbar__view
里面放着所有的元素,而el-scrollbar__wrap
是一个固定高度的容器,那么只需要获取到el-scrollbar__wrap
这个DOM,并且再给一个定时器,不断的改变它的scrollTop
值,就可以实现自动滚动的效果,这个值必须要用一个变量来存储,不然会失效停止和继续滚动思路
boolean
类型变量,每次执行定时器的时候判断一下,true
就滚动,否则就不滚动滚轮事件思路
el-scrollbar__wrap
的scrollTop
赋给前面存储的变量,这样执行定时器的时候,就可以继续在当前位置滚动不滚动的思路
el-scrollbar__view
这个容器的高度,是否大于el-scrollbar__wrap
的高度,是就可以滚动,不是就不滚动。大致的思路是这样的,下面上源码
实现代码
文件名:tableAutoScroll.ts
interface ElType extends HTMLElement { timer: number | null isScroll: boolean curTableTopValue: number}exportdefault { created(el: ElType) { el.timer = null el.isScroll = true el.curTableTopValue = 0 }, mounted(el: ElType, binding: { value?: { delay?: number } }) { const { delay = 15 } = binding.value || {} const tableDom = el.getElementsByClassName( 'el-scrollbar__wrap' )[0] as HTMLElement const viewDom = el.getElementsByClassName( 'el-scrollbar__view' )[0] as HTMLElement const onMouseOver = () => (el.isScroll = false) const onMouseOut = () => { el.curTableTopValue = tableDom.scrollTop el.isScroll = true } tableDom.addEventListener('mouseover', onMouseOver) tableDom.addEventListener('mouseout', onMouseOut) el.timer = window.setInterval(() => { const viewDomClientHeight = viewDom.scrollHeight const tableDomClientHeight = el.clientHeight if (el.isScroll && viewDomClientHeight > tableDomClientHeight) { const curScrollPosition = tableDom.clientHeight + el.curTableTopValue el.curTableTopValue = curScrollPosition === tableDom.scrollHeight ? 0 : el.curTableTopValue + 1 tableDom.scrollTop = el.curTableTopValue } }, delay) }, unmounted(el: ElType) { if (el.timer !== null) { clearInterval(el.timer) } el.timer = null const tableDom = el.getElementsByClassName( 'el-scrollbar__wrap' )[0] as HTMLElement tableDom.removeEventListener('mouseover', () => (el.isScroll = false)) tableDom.removeEventListener('mouseout', () => { el.curTableTopValue = tableDom.scrollTop el.isScroll = true }) },}
上面代码中,我在 「created」中初始化了三个变量,分别用于存储,定时器对象 、是否滚动判断、滚动当前位置。
在 「mounted」中我还获取了一个「options」,主要是为了可以定制滚动速度
「用法」
将这段代码放在你的文件夹中
main.ts
中注册这个指令import tableAutoScroll from './modules/tableAutoScroll.ts'const directives: any = { tableAutoScroll,}/** * @function 批量注册指令 * @param app vue 实例对象 */export const install = (app: any) => { Object.keys(directives).forEach((key) => { app.directive(key, directives[key]) // 将每个directive注册到app中 })}
我这边是将自己的弄了一个批量注册,正常使用就像官网里面注册指令就可以了
el-table
上使用这个指令就可以<!-- element 列表滚动指令插件 --><template> <div class="container"> <el-table v-tableAutoScroll :data="tableData" height="300"> <el-table-column prop="date" label="时间" /> <el-table-column prop="name" label="名称" /> <el-table-column prop="address" label="Address" /> </el-table> <!-- delay:多少毫秒滚动一次 --> <el-table v-tableAutoScroll="{ delay: 50, }" :data="tableData" height="300" > <el-table-column prop="date" label="时间" /> <el-table-column prop="name" label="名称" /> <el-table-column prop="address" label="Address" /> </el-table> </div></template><script setup lang="ts">import { ref, onMounted } from 'vue'const tableData = ref<any>([])onMounted(() => { tableData.value = Array.from(Array(100), (item, index) => ({ date: '时间' + index, name: '名称' + index, address: '地点' + index, })) console.log('👉 ~ tableData.value=Array.from ~ tableData:', tableData)})</script><style lang="scss" scoped>.container { height: 100%; display: flex; align-items: flex-start; justify-content: center; gap: 100px; .el-table { width: 500px; }}</style>
上面这个例子,分别演示两种调用方法,带参数和不带参数
最后
做了这个工具之后,突然有很多思路,打算后面再做几个,做成一个开源项目,一个开源的vue3指令集
(创作者训练营强势上线,速戳上图了解)
点击"阅读原文"了解详情~