vue3+iview的Table,实现表格自动滚动

主要代码:


 const startAutoScroll = () => {
    intervalId.value && clearInterval(intervalId.value)

    intervalId.value = setInterval(() => {
      if (!containerRef.value) return

      // 使用类型断言来确保 TypeScript 识别 tableRef 属性
      let target = (containerRef.value as any).tableRef?.$el.querySelector('.ivu-table-body')

      target.scrollTop += 40 // 滚动两行的高度(假设行高25px)
      console.log('自动滚动控制', target.scrollTop)
      // 滚动到底部检测
      if (target.scrollTop + target.clientHeight >= target.scrollHeight - 10) {
        pagination.current++
        getTableData()
      }
    }, 1500)
  }

const getTableData = async () => {
    if (loading.value) return

    loading.value = true
    try {
      const res = await api({
        index: pagination.current,
        size: pagination.pageSize,
      })
      console.log('表格数据', res)
      tableData.value = formatResult ? formatResult(res) : res.records
      // 自动滚动控制
      if (autoScroll) {
        startAutoScroll()
      }
      // 分页循环逻辑
      if (tableData.value && tableData.value?.length < pagination.pageSize) {
        pagination.current = 1 // 重置到第一页
        let target = (containerRef.value as any).tableRef?.$el.querySelector('.ivu-table-body')
        target.scrollTop = 0 // 滚动两行的高度(假设行高25px)
        await nextTick()
        await getTableData() // 立即重新获取
      }
      setTotal(res.total)
      onSuccess && onSuccess()
    } catch (error) {
      //
    } finally {
      loading.value = false
    }
  }

全部文件:
useTable.ts

import { usePagination } from '@/compositionAPI/table/usePagination'
import { useDebounceFn } from '@vueuse/core'
import { ElMessage, ElMessageBox, ElLoading } from 'element-plus'

interface Options<T> {
  formatResult?: (data: T[]) => any
  onSuccess?: () => void
  immediate?: boolean
  rowKey?: keyof T
  moduleUrl?: string //接口前缀
  autoScroll?: boolean //自动滚动到顶部
}
export const useTable = <T>(api: any, options?: Options<T>) => {
  const { formatResult, onSuccess, immediate, rowKey, moduleUrl, autoScroll } = options || {}
  const { pagination, setTotal } = usePagination(() => getTableData())
  const loading = ref(false)
  const tableData = ref([])
  // const intervalId = ref<NodeJS.Timeout>()
  const intervalId = ref<number>()
  const containerRef = ref<HTMLElement>()
  // const getTableData = useDebounceFn(async () => {
  const getTableData = async () => {
    if (loading.value) return

    loading.value = true
    try {
      const res = await api({
        index: pagination.current,
        size: pagination.pageSize,
      })
      console.log('表格数据', res)
      tableData.value = formatResult ? formatResult(res) : res.records
      // 自动滚动控制
      if (autoScroll) {
        startAutoScroll()
      }
      // 分页循环逻辑
      if (tableData.value && tableData.value?.length < pagination.pageSize) {
        pagination.current = 1 // 重置到第一页
        let target = (containerRef.value as any).tableRef?.$el.querySelector('.ivu-table-body')
        target.scrollTop = 0 // 滚动两行的高度(假设行高25px)
        await nextTick()
        await getTableData() // 立即重新获取
      }
      setTotal(res.total)
      onSuccess && onSuccess()
    } catch (error) {
      //
    } finally {
      loading.value = false
    }
  }
  // }, 500)
  // 自动滚动实现
  const startAutoScroll = () => {
    intervalId.value && clearInterval(intervalId.value)

    intervalId.value = setInterval(() => {
      if (!containerRef.value) return

      // 使用类型断言来确保 TypeScript 识别 tableRef 属性
      let target = (containerRef.value as any).tableRef?.$el.querySelector('.ivu-table-body')

      target.scrollTop += 40 // 滚动两行的高度(假设行高25px)
      console.log('自动滚动控制', target.scrollTop)
      // 滚动到底部检测
      if (target.scrollTop + target.clientHeight >= target.scrollHeight - 10) {
        pagination.current++
        getTableData()
      }
    }, 1500)
  }


  // 清理定时器
  onUnmounted(() => {
    intervalId.value && clearInterval(intervalId.value)
  })
getTableData()
  return {
    loading,
    tableData,
    getTableData,
    pagination,
    containerRef,
  }
}

MainTbl.vue 重点 ref:tableRef

<template>
 <Table
      :columns="columnsVM"
      :data="data"
      :loading="loading"
      ref="tableRef"
      draggable
      :class="ns.e('table')"
      v-bind="$attrs"
      id="tableRef"
      :height="height || heightTableNumb"
    >
      <!--  -->
      <!-- 操作栏 -->
      <template #action="scope">
        <ActionBtns :scope="scope"></ActionBtns>
      </template>
      <template #[slotName]="slotProps" v-for="(slot, slotName) in $slots">
        <slot :name="slotName" v-bind="slotProps" />
      </template>
    </Table>
    <Page
      v-if="Object.keys(pagination).length"
      v-model="paginationVM.current"
      :total="paginationVM.total"
      :page-size="paginationVM.pageSize"
      size="small"
      show-elevator
      show-sizer
      show-total
      @on-change="paginationVM.onChange"
      @on-page-size-change="paginationVM.onPagesizechange"
      ref="pageRef"
    />
</template>

使用ParkCompany.vue,引入:MainTbl

<template>
  
    <MainTbl
      ref="containerRef"
      :data="tableData"
      v-model:columns="columns"
      :loading="loading"
      :showIndex="false"
      :height="contentH"
    >
    </MainTbl>
 
......

import MainTbl from '@/components/common/mainTbl/MainTbl.vue'
......

</template>
posted @ 2025-04-24 11:41  sinceForever  阅读(141)  评论(0)    收藏  举报