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,转载请注明出处,谢谢。

上一篇 下一篇

猜你喜欢

热点阅读