amis PaginationWrapper 分页容器组件实战:给任意列表数据接入前端分页
amis PaginationWrapper 分页容器组件实战给任意列表数据接入前端分页【免费下载链接】amis前端低代码框架通过 JSON 配置就能生成各种页面。项目地址: https://gitcode.com/GitHub_Trending/am/amisPaginationWrapper分页容器是 amis 中负责「数据分页」的功能性渲染器它本身不负责拉取数据而是把作用域中已有的数组按每页条数切分后下发给内容区让 Table、List 等任意列表型组件获得前端分页能力。本文以 PaginationWrapper 官方文档 为主线结合 amis 仓库中的渲染器源码、分页状态存储与测试用例完整讲解该组件的属性配置、数据流原理与落地写法读完即可在自己的页面中直接复用。组件定位只做分页不碰数据请求PaginationWrapper 是 amis 中一个典型的功能性非展示型渲染器核心职责只有两件事输入默认读取当前作用域中的items变量如果你的数据存放在其他变量名下通过配置inputName指定。输出分页处理后把「当前页数据」下发给outputName默认同样是items对应的数据供内容区body中的组件使用。从源码看它被注册为pagination-wrapper渲染器并挂载了独立的分页状态存储渲染器注册PaginationWrapper.tsx状态存储pagination.ts也就是说PaginationWrapper 适合用于「接口一次性返回全量数据、前端本地翻页」的场景例如配合service拉取列表后再分页展示。快速上手一个可直接运行的完整示例下面是官方文档给出的标准用法service通过接口获取数据后交给pagination-wrapper做前端分页table只负责展示当前页数据{ type: service, api: /api/mock2/crud/table, body: [ { type: pagination-wrapper, inputName: rows, outputName: rows, perPage: 2, body: [ { type: table, title: 分页表格, source: ${rows}, columns: [ { name: engine, label: Engine }, { name: version, label: Version } ] } ] } ] }要点拆解service接口返回的数据落在作用域中其中列表数组存放在rows变量里pagination-wrapper通过inputName: rows指定输入字段outputName: rows指定输出字段perPage: 2表示每页 2 条body内嵌的table通过source: ${rows}读取分页后的数据——注意这里读取的已经是「当前页切片」后的数组分页条默认显示在内容区上方position默认值为top。这个例子清晰地展示了组件的典型工作流作用域数组 → 切片 → 重新注入作用域 → 内容区消费。属性配置详解官方属性表如下参数含义已完整保留属性名类型默认值说明typestringpagination-wrapper指定为 Pagination-Wrapper 渲染器showPageInputbooleanfalse是否显示快速跳转输入框maxButtonsnumber5最多显示多少个分页按钮inputNamestringitems输入字段名outputNamestringitems输出字段名perPagenumber10每页显示多条数据positiontop或bottom或nonetop分页显示位置配置为none时需要自己在内容区配置pagination组件否则不显示bodySchemaNode内容区域其中几个关键属性在源码中的落点inputName / outputName / perPage / position是渲染器的默认属性见 PaginationWrapper.tsx 中的defaultPropsinputName: items、outputName: items、perPage: 10、position: top与官方属性表完全一致showPageInput / maxButtons并不直接作用于 PaginationWrapper 本身而是透传给内部渲染的分页条组件见下文「与 Pagination 组件的协作」。补充从源码看虽然官方属性表未列出但组件在构造与更新时会通过store.syncProps把mode、ellipsisPageGap一并同步到分页状态存储PaginationWrapper.tsx 实际路径为 PaginationWrapper.tsx。因此你可以在节点上直接传mode分页模式与ellipsisPageGap省略号间隔来控制分页条外观这在源码层面是受支持的。工作原理源码级拆解1. 分页状态存储 PaginationStorePaginationWrapper 使用独立的 PaginationStoremobx-state-tree 定义核心状态与计算逻辑如下.props({ page: 1, // 当前页码 perPage: 10, // 每页条数 inputName: , // 输入字段名 outputName: , // 输出字段名 mode: normal, // 分页模式 ellipsisPageGap: 5 })三个关键的派生数据viewsinputItems通过resolveVariable(self.inputName || items, self.data)从作用域读取输入数组若解析结果不是数组则返回空数组保证健壮性locals计算skip (page - 1) * perPage对输入数组做slice(skip, skip perPage)得到当前页数据并通过createObject生成一个新作用域对象其中包含currentPage当前页码lastPage总页数outputName默认items当前页切片后的数组。lastPageMath.ceil(inputItems.length / perPage)向上取整得到总页数。数据变更动作actions只有switchTo(page, perPage?)设置当前页码若传入perPage则同时更新每页条数。这解释了翻页按钮点击后的完整链路。2. 渲染与数据下发渲染器 PaginationWrapper.tsx 的render方法逻辑清晰当position ! none时渲染一个内置的pagination组件并绑定activePage: store.page、lastPage: store.lastPagemode: store.mode、ellipsisPageGap: store.ellipsisPageGaponPageChange: store.switchTo点击页码即切换状态perPage: store.perPagebody内容区通过render(body, body, {data: store.locals})渲染把分页后的新作用域注入给子组件——这正是table能通过${rows}读到当前页数据的原因分页条的位置由position决定top显示在内容上方bottom显示在下方若未配置body则渲染一个占位提示PaginationWrapper.placeholder。因此整个数据流可以概括为作用域数组(inputName) ── PaginationStore.inputItems │ ├── slice 切片 ── locals[outputName] ── body 内组件消费 │ └── 页码切换 store.switchTo ── 重新切片 ── 页面更新3. 与 Pagination 组件的协作当position不为none时PaginationWrapper 内部渲染的其实是一个标准的 pagination 组件。因此该组件的部分外观/交互属性在 PaginationWrapper 上同样生效showPageInput是否显示快速跳转输入框默认falsemaxButtons最多显示多少个分页按钮默认5此外pagination组件本身还支持layout控制分页结构顺序、modenormal/simple、showPerPage、perPageAvailable可切换的每页条数列表、disabled等属性见 Pagination.tsx需要更复杂分页交互时可自行扩展。值得注意pagination组件在触发翻页时会先派发change事件可通过事件动作拦截或监听见 Pagination.tsx随后才调用onPageChange完成页码切换。4. position none完全自定义分页条如果希望分页条出现在内容区的中间、或者使用完全自定义的分页样式可以将position配置为none。此时组件不会渲染内置分页条你需要自己在body中放置一个pagination组件并手动接上数据{ type: pagination-wrapper, inputName: rows, outputName: rows, perPage: 5, position: none, body: [ { type: table, source: ${rows}, columns: [...] }, { type: pagination, activePage: ${currentPage}, lastPage: ${lastPage}, onPageChange: ... } ] }因为locals作用域中已注入currentPage和lastPage两个变量内容区里的pagination组件可以直接读取它们来渲染页码状态。这里onPageChange需要通过事件动作如 事件动作 中的自定义 JS/调用组件方法驱动store.switchTo属于进阶用法如果只是想调整分页条在内容区中间展示更推荐使用自定义布局或插槽方案。测试用例验证仓库中提供了针对该组件的集成测试 paginationWrapper.test.tsx可以佐证其行为测试通过 mockfetcher返回 2 条数据items数组页面结构为page - service - pagination-wrapper - crud其中pagination-wrapper配置了inputName: items、outputName: items、perPage: 20、position: bottom断言表格渲染出的单元格内容与接口返回数据一致说明「接口数据 → 分页切片 → 内容区消费」的链路在perPage大于数据总量时能完整透传所有数据。从该测试还能看到PaginationWrapper 不止可以包裹table同样可以包裹crud通过source指定数据源说明其内容区可以容纳任意 SchemaNode。实战建议与注意事项数据必须已存在于作用域PaginationWrapper 是纯前端分页不会触发任何网络请求。请先通过service、api或父级页面数据将完整列表注入作用域再交给它切片。inputName 与 outputName 可以不同名例如接口返回data.rows可以配置inputName: rows、outputName: pageRows内容区用${pageRows}消费互不干扰。perPage 的语义默认 10 条/页切片逻辑为(page - 1) * perPage起、perPage长度总页数为Math.ceil(length / perPage)当perPage大于数据总量时直接展示全部数据。位置选择分页条默认在顶部top列表较长、希望翻页后视线留在底部时用bottom需要完全自定义时用none并在内容区自行放置pagination。与 CRUD 组件区分CRUD 自带服务端分页配合接口page/perPage参数而 PaginationWrapper 面向的是「一次性拿全量、前端本地翻页」的场景两者适用边界不同按数据量级选择。PaginationWrapper 是 amis 中「数据切分 作用域重注入」设计模式的典型代表不渲染任何具体 UI只负责把大数组按页切开并塞回作用域。理解了它的inputName/outputName数据流与PaginationStore的切片逻辑你就能在任意列表场景中快速接入前端分页能力。【免费下载链接】amis前端低代码框架通过 JSON 配置就能生成各种页面。项目地址: https://gitcode.com/GitHub_Trending/am/amis创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考