You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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)
    

二、滚动检测逻辑优化

你的伪代码中用固定数值判断滚动位置不可靠,改成基于容器尺寸的动态判断,同时加防抖和加载锁避免重复触发:

  1. 替换固定阈值:用scrollHeight - scrollTop <= clientHeight + 10(10px是容错阈值)判断是否到达底部,适配不同尺寸的容器
  2. 添加防抖:避免滚动过程中频繁触发检测,减少性能消耗
  3. 添加加载锁:防止滚动时多次触发加载逻辑

优化后的方法示例:

// 自定义防抖函数
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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 10:02:12