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

vue3+js实现表格虚拟滚动

VirtualTable.vue

<template><div class="virtual-table"><!-- 表头固定 --><div class="table-header"><div v-for="col in columns" :key="col.key" :style="{ width: col.width + 'px' }">{{ col.title }}</div></div><!-- 滚动区域 --><div class="scroll-body" ref="scrollContainer" @scroll="handleScroll" :style="{ height: scrollHeight + 'px' }"><!-- 撑开滚动条的占位元素 --><div class="phantom" :style="{ height: totalHeight + 'px' }"></div><!-- 实际渲染的可见行 --><div class="row" v-for="item in visibleData" :key="item[rowKey]" :style="{ transform: `translateY(${item.offset}px)` }"><div v-for="col in columns" :key="col.key" :style="{ width: col.width + 'px' }">{{ item[col.dataIndex] }}</div></div></div></div>
</template><script>import { ref, computed, onMounted } from 'vue';export default {props: {dataSource: {type: Array,required: true,},columns: {type: Array,required: true,},rowHeight: {type: Number,default: 55,},bufferSize: {type: Number,default: 5,},scrollHeight: {type: Number,default: 400,},rowKey: {type: String,default: 'id',},},setup(props) {const scrollContainer = ref(null);const scrollTop = ref(0);// 计算总高度const totalHeight = computed(() => props.dataSource.length * props.rowHeight);// 计算可见范围const range = computed(() => {const startIdx = Math.max(0, Math.floor(scrollTop.value / props.rowHeight) - props.bufferSize);const endIdx = Math.min(props.dataSource.length, startIdx + Math.ceil(props.scrollHeight / props.rowHeight) + props.bufferSize * 2);return { startIdx, endIdx };});// 生成可见数据const visibleData = computed(() => {return props.dataSource.slice(range.value.startIdx, range.value.endIdx).map((row, i) => ({...row,offset: (range.value.startIdx + i) * props.rowHeight,}));});// 滚动事件处理const handleScroll = (e) => {scrollTop.value = e.target.scrollTop;};return {scrollContainer,totalHeight,visibleData,handleScroll,};},};
</script><style scoped>.virtual-table {width: 100%;border: 1px solid #e8e8e8;}.table-header {display: flex;background: #fafafa;font-weight: 500;border-bottom: 1px solid #f0f0f0;}.scroll-body {position: relative;overflow-y: auto;will-change: transform;}.phantom {position: absolute;left: 0;top: 0;right: 0;z-index: -1;}.row {position: absolute;width: 100%;display: flex;border-bottom: 1px solid #f0f0f0;box-sizing: border-box;}
</style>

引用
testTable.vue

<template><VirtualTable :data-source="tableData" :columns="columns" row-key="id" scroll-height="500" />
</template><script>import { ref } from 'vue';import VirtualTable from './VirtualTable.vue';export default {components: { VirtualTable },setup() {// 生成测试数据const tableData = ref(Array.from({ length: 1000 }, (_, i) => ({id: i + 1,name: `用户${i + 1}`,age: Math.floor(Math.random() * 50) + 18,address: `地址${Math.floor(Math.random() * 1000)}`,})));const columns = ref([{ key: 'name', title: '姓名', dataIndex: 'name', width: 150 },{ key: 'age', title: '年龄', dataIndex: 'age', width: 100 },{ key: 'address', title: '地址', dataIndex: 'address', width: 300 },]);return { tableData, columns };},};
</script>

浏览器运行效果
在这里插入图片描述

http://www.lqws.cn/news/487009.html

相关文章:

  • OpenCV计算机视觉实战(12)——图像金字塔与特征缩放
  • Android 15 变更及适配攻略
  • 代码分析与自动化重构
  • Mysql常见的SQL语句格式
  • 【MySQL基础】MySQL复合查询全面解析:从基础到高级应用
  • Blazor-EditContext
  • 智能化战略实施服务,AI咨询与部署全流程支持
  • [2025CVPR]DeepLA-Net:深度局部聚合网络解析
  • STaR: Self-Taught Reasoner Bootstrapping Reasoning With Reasoning论文笔记
  • ISCSI存储
  • Java性能优化权威指南-操作系统性能监控
  • FreeRTOS 介绍、使用方法及应用场景
  • redis如何使用IO多路复用
  • 从语言到生态:编程语言在各行业的应用格局与未来演进
  • Data Vault 初探(五) —— 定期装载_SQL
  • 从java角度理解io多路复用和redis为什么使用io多路复用
  • docker启动的rabbitmq搭建并集群和高可用
  • AS32系列MCU芯片I2C模块性能解析与调试
  • 秘塔AI搜索:国产无广告智能搜索引擎,重塑高效信息获取体验
  • 1 Studying《Systems.Performance》1-6
  • 跨域视角下强化学习重塑大模型推理:GURU框架与多领域推理新突破
  • 黑马python(十三)
  • 二刷苍穹外卖 day03
  • K8s入门指南:架构解析浓缩版与服务间调用实战演示
  • C#Halcon从零开发_Day14_AOI缺陷检测策略1_Bolb分析+特征分析_饼干破损检测
  • 国产12537穿甲弹侵彻仿真(显式动力学)
  • DeepSeek15-揭密模型上下文协议(MCP)
  • 从零开始手写redis(15)实现自己的 HashMap
  • 大模型LoRA微调实践
  • C语言:位段