Vue中实现双滚动列的分页/无限滚动方案咨询
分页结合无限滚动的实现建议
一、数组拆分与渲染控制
针对两个不同规模的列表,核心是维护全量数据数组和当前渲染数组,通过分页切片实现懒加载:
- 为每个列表定义独立状态:
allSuppliers/allClients:存储从数据库加载的全量数据displayedSuppliers/displayedClients:存储当前需要渲染的条目currentPageXxx:当前加载的页码pageSize:每页加载的条目数(建议根据容器高度和单条item高度设置,比如供应商列表设50-100,客户列表因数据量大可调至30-50)
- 初始化时先加载第一页:
this.displayedSuppliers = this.allSuppliers.slice(0, this.pageSize) this.displayedClients = this.allClients.slice(0, this.pageSize)
二、滚动检测逻辑优化
你的伪代码中用固定数值判断滚动位置不可靠,改成基于容器尺寸的动态判断,同时加防抖和加载锁避免重复触发:
- 替换固定阈值:用
scrollHeight - scrollTop <= clientHeight + 10(10px是容错阈值)判断是否到达底部,适配不同尺寸的容器 - 添加防抖:避免滚动过程中频繁触发检测,减少性能消耗
- 添加加载锁:防止滚动时多次触发加载逻辑
优化后的方法示例:
// 自定义防抖函数 debounce(func, delay) { let timer return function(...args) { clearTimeout(timer) timer = setTimeout(() => func.apply(this, args), delay) } }, mounted() { // 绑定防抖后的滚动事件 this.debouncedPaginate = this.debounce(this.paginateDatasets, 50) this.$refs.listColSuppliers.addEventListener('scroll', () => this.debouncedPaginate('suppliers')) this.$refs.listColClients.addEventListener('scroll', () => this.debouncedPaginate('clients')) }, beforeUnmount() { // 移除事件监听,避免内存泄漏 this.$refs.listColSuppliers.removeEventListener('scroll', () => this.debouncedPaginate('suppliers')) this.$refs.listColClients.removeEventListener('scroll', () => this.debouncedPaginate('clients')) }, paginateDatasets(col) { if (!this.store.supplierFound || !this.store.clientFound) { switch(col) { case 'suppliers': const container = this.$refs.listColSuppliers const diff = container.scrollHeight - container.scrollTop // 滚动到底部且未在加载中 if (diff <= container.clientHeight + 10 && !this.isLoadingSuppliers) { this.isLoadingSuppliers = true const nextPage = this.currentPageSuppliers + 1 const start = nextPage * this.pageSize const end = start + this.pageSize const newItems = this.allSuppliers.slice(start, end) if (newItems.length) { this.displayedSuppliers = [...this.displayedSuppliers, ...newItems] this.currentPageSuppliers = nextPage } this.isLoadingSuppliers = false } break case 'clients': const clientContainer = this.$refs.listColClients const diffClient = clientContainer.scrollHeight - clientContainer.scrollTop if (diffClient <= clientContainer.clientHeight + 10 && !this.isLoadingClients) { this.isLoadingClients = true const nextPage = this.currentPageClients + 1 const start = nextPage * this.pageSize const end = start + this.pageSize const newItems = this.allClients.slice(start, end) if (newItems.length) { this.displayedClients = [...this.displayedClients, ...newItems] this.currentPageClients = nextPage } this.isLoadingClients = false } break } } }
三、Vue渲染性能优化
- 给
v-for循环添加唯一:key="item.id",帮助Vue复用DOM节点,减少重排重绘 - 对于58000条的clients列表,若懒加载仍有性能问题,建议用虚拟滚动:只渲染可视区域内的条目,比如自己实现简单虚拟滚动(计算可视区域的item索引范围,只渲染对应切片),避免一次性渲染大量DOM
- 避免在
v-for中使用v-if控制显示,直接通过displayedXxx数组控制渲染条目,更高效
四、Electron特定优化
- 若全量数据过大(比如58000条),建议后端分页拉取,而非一次性加载全量到前端内存,减少Electron进程的内存占用
- 滚动检测逻辑可结合
requestAnimationFrame执行,让浏览器在重绘前处理,提升流畅度
内容的提问来源于stack exchange,提问作者OHICT
相关产品推荐
相关产品推荐

