当前位置: 首页 > news >正文

vue3+elementPlus实现无缝滚动表格封装

vue3+elementPlus+css+js 模拟liMarquee插件,实现无限滚动效果

功能:1、表格数据大于一定数量之后,开始向上滚动

           2、当鼠标移入的时候,动画停止,鼠标移出,继续动画

           3、滚动动画的速度可以自定义

           4、表格的高度固定

           5、向上滚动时,无限滚动,不存在卡顿

<template>

  <div

    class="scrolling-table-container"

    @mouseenter="pauseAnimation"

    @mouseleave="resumeAnimation"

  >

    <div class="table-wrapper" :style="{ height: tableHeight }">

      <el-table

        :data="displayData"

        :loading="loading"

        style="width: 100%"

        :show-header="showHeader"

        :row-key="rowKey"

        class="scrolling-table"

        :class="{

          'enable-scroll': needScroll,

          'is-paused': isPaused

        }"

      >

        <el-table-column

          v-for="column in columns"

          :key="column.prop"

          :prop="column.prop"

          :label="column.label"

          :width="column.width"

          :min-width="column.minWidth"

          :fixed="column.fixed"

        >

          <template #default="scope" v-if="column.hasSlot">

            <slot :name="column.prop" :row="scope.row" :index="scope.$index"></slot>

          </template>

        </el-table-column>

      </el-table>

    </div>

  </div>

</template>

<script setup lang="ts" name="ScrollingTable">

import { ref, computed, watch, onMounted, onBeforeUnmount } from 'vue'

import { ElTable, ElTableColumn } from 'element-plus'

interface TableColumn {

  prop: string

  label: string

  width?: string | number

  minWidth?: string | number

  fixed?: string | boolean

  hasSlot?: boolean

}

interface ScrollingTableProps {

  tableData: Record<string, unknown>[]

  columns: TableColumn[]

  loading?: boolean

  rowKey?: string

  showHeader?: boolean

  tableHeight?: string

  scrollThreshold?: number

  scrollSpeed?: number

  scrollDelay?: number

}

const props = withDefaults(defineProps<ScrollingTableProps>(), {

  loading: false,

  rowKey: 'id',

  showHeader: true,

  tableHeight: '250px',

  scrollThreshold: 8,

  scrollSpeed: 120,

  scrollDelay: 2000

})

const displayData = ref<Record<string, unknown>[]>([])

const isPaused = ref(false)

let delayTimer: number | null = null

// 计算是否需要滚动

const needScroll = computed(() => props.tableData.length > props.scrollThreshold)

// 计算动画持续时间

const animationDuration = computed(() => {

  if (!needScroll.value) return 0

  // 基于数据长度计算合适的动画时间,确保平滑滚动

  return Math.max(props.tableData.length * props.scrollSpeed, 3000)

})

// 初始化显示数据

const initDisplayData = () => {

  if (needScroll.value && props.tableData.length > 0) {

    // 为无缝滚动复制数据

    displayData.value = [

      ...props.tableData,

      ...props.tableData

    ]

  } else {

    displayData.value = [...props.tableData]

  }

}

// 启动动画(延迟)

const startAnimation = () => {

  if (!needScroll.value) return

  clearTimeout(delayTimer!)

  delayTimer = setTimeout(() => {

  }, props.scrollDelay)

}

// 停止所有定时器

const stopTimers = () => {

  if (delayTimer) {

    clearTimeout(delayTimer)

    delayTimer = null

  }

}

// 暂停动画

const pauseAnimation = () => {

  isPaused.value = true

}

// 恢复动画

const resumeAnimation = () => {

  isPaused.value = false

}

// 重新初始化

const reinitialize = () => {

  stopTimers()

  isPaused.value = false

  initDisplayData()

  startAnimation()

}

// 监听数据变化

watch(() => props.tableData, () => {

  reinitialize()

}, { immediate: true })

// 监听配置变化

watch([

  () => props.scrollThreshold,

  () => props.scrollSpeed,

  () => props.scrollDelay

], () => {

  reinitialize()

})

onMounted(() => {

  startAnimation()

})

onBeforeUnmount(() => {

  stopTimers()

})

// 暴露方法

defineExpose({

  reinitialize,

  needScroll,

  pauseAnimation,

  resumeAnimation

})

</script>

<style lang="scss" scoped>

.scrolling-table-container {

  cursor: default;

  :deep(.el-table thead){

    color: #242933 !important;

    font-weight: 500;

  }

  .table-wrapper {

    overflow: hidden;

    position: relative;

     :deep(.el-table thead th.el-table__cell) {

        background: #F8F9FA !important;

      }

  }

  .scrolling-table {

    // 基本样式

    :deep(.el-table__body-wrapper) {

      overflow: hidden !important;

     

      &::-webkit-scrollbar {

        display: none;

      }

    }

   

    :deep(.el-table__header-wrapper) {

      overflow-x: hidden;

    }

    :deep(.el-table thead){

      color: #242933 !important;

      font-weight: 500;

    }

    :deep(.el-table__row) {

      transition: none;

    }

   

    :deep(.el-table__body) {

      transition: none;

    }

   

    // 鼠标悬停样式

    :deep(.el-table__row):hover {

      background-color: #f5f7fa;

    }

   

    // 启用滚动时的动画

    &.enable-scroll :deep(.el-table__body) {

      animation: scroll-up v-bind("animationDuration + 'ms'") linear infinite;

      animation-delay: v-bind("scrollDelay + 'ms'");

    }

   

    // 暂停状态

    &.is-paused :deep(.el-table__body) {

      animation-play-state: paused;

    }

  }

}

// 滚动动画关键帧 - 无限向上滚动

@keyframes scroll-up {

  0% {

    transform: translateY(0);

  }

  100% {

    transform: translateY(-50%);

  }

}

// 响应式优化

@media (prefers-reduced-motion: reduce) {

  .scrolling-table.enable-scroll :deep(.el-table__body) {

    animation: none;

  }

}

</style>

相比liMarquee,优点如下:

1、不用使用npm 安装liMarquee包

2、liMarquee是基于jquery的,使用liMarquee,还得安装jquery

3、使用js、css 实现动画效果,性能友好

相关文章:

  • springboot 接口参数接收,body和param什么区别,分别怎么使用
  • SpringCloud+Vue汽车、单车充电桩源码实现:从架构设计到核心模块解析
  • Prufer序列 学习笔记
  • SNMPv3 的安全命名空间详解
  • 需要做一款小程序,用来发券,后端如何进行设计能够保证足够安全?
  • MySQL 多表查询、事务
  • 交叉熵损失函数的优势
  • Java常见异常详解及解决方案(九)
  • 【Git】关于项目开发分支的使用规范
  • 分库分表之优缺点分析
  • 结合 STM32CubeMX 使用 FreeRTOS 实时操作系统
  • XXE(XML外部实体注入)详解
  • 基于集体智能长尾识别的超声乳腺病变亚型分类|文献速递-深度学习医疗AI最新文献
  • [Jenkins在线安装]
  • 关于机器学习中迁移学习与深度学习的思考
  • CMake基础:常用内部变量和环境变量的引用
  • ntfs!CcGetDirtyPages函数分析之DirtyPages=0x1和TargetAttribute=0xe0的一个例子
  • 借助AI学习编程,走向架构师之路
  • AntV F2入门教程
  • OpenCV CUDA模块设备层---- 绝对值函数abs()
  • 微站网建站系统/免费推广网站视频
  • 网站制作中企动力/百度优化推广
  • 旅游网站建设费用/学网络运营在哪里学比较好
  • 网络公司给别人做网站的cms是买的授权么/南昌seo排名扣费
  • 做外贸网站推广/外贸营销型网站建设公司
  • 网站被抄袭怎么办/外贸推广哪个公司好