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

vue3 elementUi Table 数据下拉懒加载

文章目录

    • 实现的背景
    • 实现思路
    • vue3实现代码
    • 注意

实现的背景

element ui 的table 没有提供下拉加载后续数据的功能,前端要想优化,要么做分页,要么做数据下拉追加。当数据太多,比如有上千条的时候,一次性渲染出来,会降低首屏加载时间,也会让页面滚动变得卡顿。

实现思路

将table组件的滚动dom找出来,对它做滚动监听,当滚动条快要到底的时候,追加100条数据。追加后,滚动条会上升,等待下一次触发快要到底的时候,追加100条数据。

vue3实现代码

<template>
  <!-- 表格 -->
  <div class="table-container" ref="tableContainer">
    <el-table
      :max-height="maxHeight"
      :data="renderData"
      v-loading="loading"
      :empty-text="'暂无数据'"
      :style="style"
    >
        <el-table-column
          v-for="column in tableColumn" :key="column?.label"
          v-bind="{...column}"
        >
    	</el-table-column>
    </el-table>
  </div>
</template>

<script lang="ts" setup name="customTable">
  const props = defineProps({
    tableData: {
      type: Array,
      default: () => [],
    },
    tableColumn: {
      type: Array<any>,
      default: () => [],
    },
    loading: {
      type: Boolean,
      default: false,
    },
    style: {
      type: Object,
      default: () => {},
    },
    maxHeight: {
      type: [String, Number],
      default: 700,
    },
  });


  // 下滑懒加载
  const tableContainer = ref(null); // 需要通过它来定位table有滚动条的dom,因为一次可能渲染很多个table,我们不能直接找那个有滚动条的table
  const pushCount = ref(1); // 追加数据的次数
  
  const renderData = computed(() => {
    return props.tableData.slice(0, pushCount.value * 100); // renderData为渲染的实际数据,pushCount变化会重新计算render的数据
  });

  const handleScroll = (event) => {
    const target = event.target as HTMLElement;
    // 判断滚动条是否快要到底了,距离底部还剩700px左右时,就要开始追加了,700为buffer值
    if (target.scrollHeight - target.scrollTop - target.clientHeight <= 700) {
      // 每一次追加都需要判断,是否还有要追加的数据,如果已经到底了,就没必要追加数据了
      if(renderData.value.length < props.tableData.length) {
        pushCount.value += 1;
      }
    }
  }
  // 把scorllBody放在这个位置,是为了方便onUnmounted时候,取消掉scroll的监听  
  let scrollBody
  
  // 有时候接收的tableData可能是变化的,一开始不到100,后来超过100,再后来又变成300,通过hasHandleScroll,来限制一个table最多只能加一个滚动	监听
  let hasHandleScroll = false

  onUnmounted(() => {
    hasHandleScroll = false
    scrollBody.removeEventListener('scroll', handleScroll, false)
  })
	
  // 通过对props.tableData的监听,来判断是否需要开启滚动监听,可能一开始不到100,后来就超过100了,需要加监听
  watch(() => props.tableData, () =>{
    nextTick(() => {
      const container = tableContainer.value as any;
      scrollBody = container?.querySelector('.el-scrollbar__wrap')

      // 需要判断一下scrollBody 是否已经有了滚动监听
      if(props.tableData.length >= pushCount.value * 100 && !hasHandleScroll) {
        scrollBody.addEventListener('scroll', handleScroll, false)
        hasHandleScroll = true
      }
    })
  },{
    immediate: true
  })

</script>

<style lang="scss">
</style>

注意

还有更多优化的空间
比如handleScroll可以通过防抖封装一下,但时间间隔不要太大,最好在50ms内。

比如每一次tableData变化时,最好先判断一下,是否需要取消监听scroll。因为有可能最开始超过100,后来又少于100,但少于100以后,如果滚动条仍存在,其实scroll监听仍然存在,这个时候其实不需要监听了。

这种优化方案,仍然不足,当用户有足够耐心,将所有数据加载完了,往上滚动时,页面仍然可能会卡顿。这个时候需要使用虚拟列表的方式来实现优化,而不仅仅只是下拉懒加载。下拉懒加载是虚拟列表的一部分。

如果是pc端,最好用分页,但如果是移动端,分页对用户的体验就不太友好。

相关文章:

  • 欢乐力扣:赎金信
  • golang调用deepseekr1
  • Kafka常用命令
  • Vue学习记录21
  • 推荐一个github star45k+进阶的java项目及知识的网站
  • vue 识别 <think></think>
  • Ubuntu 服务器Llama Factory 搭建DeepSeek-R1微调训练环境
  • HTTP请求状态码
  • YOLOv11-ultralytics-8.3.67部分代码阅读笔记-build.py
  • 51单片机学习——静态数码管显示
  • 设计模式教程:装饰器模式(Decorator Pattern)
  • springboot404-基于Java的校园礼服租赁系统(源码+数据库+纯前后端分离+部署讲解等)
  • leetcode刷题-动态规划07
  • docker 安装jenkins
  • 使用 Spark NLP 实现中文实体抽取与关系提取
  • lab4 CSAPP:Cachelab
  • 机器学习数学基础:28.卡方检验
  • Windows 图形显示驱动开发-驱动驻留的供应和回收更改
  • 网安作业3
  • 【Linux C/C++开发】udev监测USB事件
  • 深圳龙岗区最新疫情/优化网站排名
  • 武汉网页平面设计/网站推广与优化平台
  • 个人备案网站放什么手续/怎样做好竞价推广
  • 外管局网站做延期收汇报告/百度推广代理
  • 百度浏览器下载/seo站长网
  • 网站seo设计方案案例/建站系统有哪些