bricks/aidocs/paging.md
2025-10-05 06:39:58 +08:00

7.6 KiB
Raw Blame History

bricks.BufferedDataLoader 技术文档

一个用于分页加载数据并支持缓冲机制的前端数据加载器。


概述

bricks.BufferedDataLoader 是一个 JavaScript 类,旨在为需要高效处理大量分页数据的 UI 组件(如表格、列表等)提供带缓冲的数据加载能力。它通过限制内存中缓存的页面数量来优化性能,并支持向前/向后翻页操作。

该类适用于与支持分页接口的后端服务配合使用,典型场景包括大数据量表格滚动加载、虚拟滚动列表等。


命名空间

bricks.BufferedDataLoader

依赖于全局对象 window.bricks,若不存在则自动创建。


构造函数

new bricks.BufferedDataLoader(widget, options)

参数

参数 类型 必填 描述
widget Object 数据展示组件实例,必须实现 .clear_data(), .add_rows(rows, direction), .del_old_rows(count, direction) 方法。
opts Object 配置选项对象,详见下表。

opts 配置项

属性 类型 可选 默认值 说明
url String - 请求数据的 API 地址。
method String 'GET' HTTP 请求方法,如 'GET''POST'
params Object {} 固定请求参数(例如过滤条件、排序字段等)。
buffer_pages Number 5 最大缓存页数,超出时将移除最旧或最新的一页以释放内存。
pagerows Number 60 每页返回的数据行数。

实例属性

属性 类型 描述
cur_page Number 当前正在加载/显示的页码(从 1 开始)。
total_records Number 总记录数(由服务器返回填充)。
total_page Number 总页数(根据 total_records / pagerows 计算得出)。
buffer Object (预留扩展)当前用于存储已加载页面数据的缓存对象(本版本未实际使用)。
buffered_pages Number 当前缓冲中的页面数量(影响是否触发旧数据清理)。
loading Boolean 标志位,表示是否正在进行网络请求。
direction String 上下方向标识:'up' 表示上一页,'down' 表示下一页,用于通知 widget 渲染策略。
cur_params Object 合并后的当前请求参数(包含固定参数和动态传参)。

方法

initial()

重置加载器状态,通常在初始化或重新加载前调用。

功能:

  • 重置当前页为 -1
  • 清空缓冲计数
  • 重置总记录数
  • 清空当前参数副本

async loadData(params)

初始化并加载第一页数据,清空现有数据。

参数:

  • params (Object, 可选): 动态附加的请求参数(会与 opts.params 合并)

返回值:

  • Promise<Object>: 解析为服务器返回的数据结构,包含:
    {
      total: 1000,
      page: 1,
      total_page: 17,
      rows: [...]
    }
    

流程:

  1. 调用 initial() 重置状态
  2. 清空 widget 显示数据
  3. 合并默认参数与传入参数
  4. 设置每页行数 (rows) 和初始页码 (page=1)
  5. 调用 loadPage() 加载第一页

示例:

const loader = new bricks.BufferedDataLoader(myWidget, {
  url: '/api/data',
  params: { category: 'A' },
  pagerows: 50
});

await loader.loadData({ search: 'keyword' }); // 发送 {category:'A', search:'keyword', rows:50, page:1}

async loadPage(page)

加载指定页码的数据(内部方法,也可手动调用)。

参数:

  • page (Number, 可选): 指定要加载的页码,默认为当前 this.cur_page + 1(如果未设置)

⚠️ 注意:此方法内部管理 cur_page,外部应优先使用 nextPage() / previousPage()

行为逻辑:

  1. 若正在加载,则直接返回(防重复提交)
  2. 若缓冲页数达到上限(buffer_pages),则调用 widget.del_old_rows() 删除旧行
  3. 构造完整请求参数(含 page, rows 等)
  4. 使用 bricks.HttpJson 发起异步请求
  5. 更新总记录数和总页数
  6. 调用 widget.add_rows() 添加新数据
  7. 增加缓冲页计数,释放加载锁

返回值:

  • Promise<Object>: 服务器响应数据

async nextPage()

加载下一页数据。

条件判断:

  • 如果已在最后一页或正在加载,则不执行任何操作。

行为:

  • 设置 direction = 'down'
  • cur_page += 1
  • 调用 loadPage()

示例:

await loader.nextPage(); // 加载第 2 页

async previousPage()

加载上一页数据。

条件判断:

  • 如果已是第一页或正在加载,则不执行。

行为:

  • 设置 direction = 'up'
  • cur_page -= 1
  • 调用 loadPage()

示例:

await loader.previousPage(); // 回退到前一页

widget 接口要求

BufferedDataLoader 依赖传入的 widget 实现以下三个方法:

方法 签名 用途
.clear_data() function(): void 清空当前所有数据显示
.add_rows(rows, direction) function(Array, String): void 添加一批数据行,direction'up''down',可用于决定插入位置
.del_old_rows(count, direction) function(Number, String): void 删除旧数据行(例如顶部或底部若干行),用于维持缓冲大小

💡 提示这些方法可结合虚拟滚动、DOM 复用等技术实现高性能渲染。


使用示例

// 定义 widget 对象(模拟组件)
const myWidget = {
  data: [],
  clear_data() {
    this.data = [];
    console.log("数据已清空");
  },
  add_rows(rows, direction) {
    if (direction === 'up') {
      this.data.unshift(...rows);
    } else {
      this.data.push(...rows);
    }
    console.log(`添加了 ${rows.length} 行数据,方向: ${direction}`);
  },
  del_old_rows(count, direction) {
    if (direction === 'up') {
      this.data.splice(-count); // 删除末尾
    } else {
      this.data.splice(0, count); // 删除开头
    }
    console.log(`删除了 ${count} 行旧数据`);
  }
};

// 创建 BufferedDataLoader 实例
const loader = new bricks.BufferedDataLoader(myWidget, {
  url: '/api/list',
  method: 'POST',
  params: { type: 'report' },
  buffer_pages: 3,
  pagerows: 20
});

// 初始加载第一页
await loader.loadData({ keyword: 'test' });

// 下一页
await loader.nextPage();

// 上一页
await loader.previousPage();

注意事项

  1. 线程安全:通过 this.loading 实现简单的并发控制,防止重复请求。
  2. 内存控制:通过 buffer_pages 控制最大缓存页数,避免内存溢出。
  3. 方向感知direction 字段帮助 widget 区分上下滑动行为,便于优化 UI 渲染。
  4. 总页数计算修正
    if (d.total_page * this.pagerows < this.total_record) {
      d.total_page += 1;
    }
    
    此处逻辑存在潜在错误(应使用向上取整),建议改为:
    d.total_page = Math.ceil(d.total / this.pagerows);
    

改进建议

问题 建议修复
total_page 计算错误 改为 Math.ceil(total / pagerows)
buffer 成员未实际使用 应实现真正的页面数据缓存以支持快速回退
缺少错误处理 httpcall 外包裹 try-catch 并抛出异常
不支持取消请求 可引入 AbortController 实现请求中断

版本信息

  • 所属库:bricks.js
  • 类名:BufferedDataLoader
  • 创建时间:未知
  • 作者:未知

📖 文档生成于2025年4月5日