vue 写个内容自动滚动的自定义指令 v-auto-scroll
2024-12-18 本文已影响0人
阿巳交不起水电费
在大屏或者某些不常使用鼠标交互的页面,数据在定时刷新,如果有个列表数据过多,需要数据自己滚动展示。这里写个通用指令,需要的地方加上即可,轻量。
功能
若容器有滚动条则开启自动滚动,鼠标移入时停止,鼠标移除时继续滚动,可设置自动滚动的动画延迟多久开始启动。目前只支持y方向的,x方向自行扩展,懒得写,加起来也简单。
代码
/**
* author: yf
* date: 20241219
* 列表自动滚动 - 目前只支持 y方向,暂时没有x方向的需求
* 功能:
* 若容器有滚动条则开启自动滚动,鼠标移入时停止,鼠标移除时继续滚动
* 使用方式:
* 方式一:在滚动节点上使用默认配置
v-auto-scroll
* 方式二:完整配置
v-auto-scroll = {
targetSelector: '.el-table__body-wrapper', // 当前指令挂载节点内部的滚动盒子,使用 el.querySelector(targetSelector) 查找,节点不存在则使用 el 节点
delayTime: 1000, // 自动滚动开启的延迟时间,单位 ms
speed: 2, // 自动滚动速度,值越小滚动速度越快,最小速度为 1
interval: 1 // 每次自动滚动时移动的距离,单位px - 注意:必须是正整数
}
*/
Vue.directive('auto-scroll', {
inserted: function (el, binding) {
// console.log(el, binding, vnode);
// 获取配置参数
let {
targetSelector = '',
delayTime = 1000, // 自动滚动开启的延迟时间,单位 ms
speed = 2, // 自动滚动速度,值越小滚动速度越快,最小速度为 1
interval = 1 // 每次自动滚动时移动的距离,单位px - 注意:必须是正整数
} = binding.value || {};
// 正整数处理
interval = Math.abs(Math.ceil(interval))
el._customData = {}; // 需要移除的
let disabledScroll = false // 禁止滚动
let delayTimeSum = 0 // 累计时间,用于判断是否达到延迟时间
// 滚动元素
let scrollTarget = targetSelector ? el.querySelector(targetSelector) : ''
scrollTarget = scrollTarget || el
if (!scrollTarget) return
// 事件处理
let customEvent = {
mouseover: function () {
disabledScroll = true
},
mouseout: function () {
disabledScroll = false
delayTimeSum = 0 // 清空
}
}
// 移入时关闭自动滚动
el.addEventListener('mouseover', customEvent.mouseover, false)
// 移出时开启自动滚动
el.addEventListener('mouseout', customEvent.mouseout, false);
// 自动滚动
let preTime = Date.now();
let curTime = null;
let diffTime = 1000 / 60 * speed; // 动画间隔
let autoScroll = () => {
if (scrollTarget.scrollHeight <= scrollTarget.clientHeight) return // 无滚动条,不具备滚动条件
if (disabledScroll) return
// 判断滚动条是否到底部
if (scrollTarget.scrollHeight - scrollTarget.scrollTop === scrollTarget.clientHeight) {
scrollTarget.scrollTop = 0
} else {
scrollTarget.scrollTop = scrollTarget.scrollTop + interval
}
}
(function animloop() {
curTime = Date.now()
if (curTime - preTime > diffTime) {
// 在延迟时间内不执行动画
if (delayTimeSum >= delayTime) {
autoScroll();
} else {
delayTimeSum += curTime - preTime
}
preTime = curTime
}
el._customData.raId = requestAnimationFrame(animloop);
})()
el._customData.customEvent = customEvent
},
/* eslint-disable no-unused-vars */
unbind(el) {
/* eslint-enable no-unused-vars */
// 解绑
let _customData = el._customData;
if (!el || !_customData) return;
cancelAnimationFrame(_customData.raId)
el.removeEventListener('mouseover', _customData.customEvent.mouseover)
el.removeEventListener('mouseout', _customData.customEvent.mouseout)
}
});
效果如下
方式一:直接添加到滚动盒子上
<ul class="test-box" v-auto-scroll>
<li v-for="item in 20" :key="item">{{item}}</li>
</ul>
GIF 2024-12-19 17-44-16.gif
方式二: element-ui 的 el-table
v-auto-scroll="{
targetSelector:'.el-table__body-wrapper'
}
image.png
GIF 2024-12-19 17-33-45.gif
若对你有帮助,请点个赞吧,若能打赏不胜感激,谢谢支持!
本文地址:https://www.jianshu.com/p/e43ceee4aeca?v=1734601770680,转载请注明出处,谢谢。