ToolJet List View 组件完全指南:数据列表、分页与子组件控制

发布时间:2026/9/12 21:11:11
ToolJet List View 组件完全指南:数据列表、分页与子组件控制 ToolJet List View 组件完全指南数据列表、分页与子组件控制【免费下载链接】ToolJetOpen-source foundation of ToolJet AI - the enterprise app generation platform for internal tools, dashboards, business applications, workflows and AI agents. Build visually, from a prompt, or from Claude Code, Codex and Cursor over MCP 项目地址: https://gitcode.com/GitHub_Trending/to/ToolJetList View 是 ToolJet 应用构建器中用于批量渲染重复行数据的核心容器组件你只需设计一行包含任意嵌套组件组件就会根据List data自动复制出多行实例。本篇指南基于当前仓库 listview.md 展开结合 listview.js 组件配置与 Listview.jsx 运行时代码完整讲解 List data 绑定、全部属性/事件/暴露变量、分页、样式定制以及通过children变量用 JS 查询控制子组件读完即可独立构建接口数据 → 列表展示 → 行交互的完整场景。一、组件定位与核心能力从组件配置源码 listview.js 可以看出List View内部组件名为Listview本质上是一个带模板子组件的容器拖入画布时自带 3 个默认子组件Image、Text、Button分别通过accessorKeyimageURL/text/buttonText与数据对象的字段自动关联默认画布尺寸为宽 15 格、高 450px你只编辑第一行模板组件会按List data的数组长度自动生成后续所有行实例。与 Container 类似List View 内部可嵌套任意组件也支持 List View 嵌套 List View多级列表。唯一的限制是Calendar 和 Kanban 组件被禁止通过拖拽放入 List View 内部。:::caution 受限组件Calendar与Kanban组件不允许拖入 List View 中使用请改用其他容器承载它们。 :::二、设置 List DatalistItem数据绑定List View 的List data属性接受对象数组或返回对象数组的查询结果。在 List View 内部每一条数据会通过约定变量listItem暴露给行模板中的子组件。官方文档示例数据{{[ { imageURL: https://www.svgrepo.com/show/34217/image.svg, text: Sample text 1, buttonText: Button 1 }, { imageURL: https://www.svgrepo.com/show/34217/image.svg, text: Sample text 1, buttonText: Button 2 }, { imageURL: https://www.svgrepo.com/show/34217/image.svg, text: Sample text 1, buttonText: Button 3 }, ]}}行内组件的绑定方式// Text 组件的 Data 属性 {{listItem.text}} // Image 组件的 source 属性 {{listItem.imageURL}}从源码看listItem的注入发生在 Listview.jsx组件会对过滤后的数据逐条执行filteredData.map((listItem) ({ listItem }))并通过updateCustomResolvables(id, listItems, listItem, ...)注册为自定义可解析变量。这意味着listItem是行作用域的——第 0 行的{{listItem.text}}取数组第 0 个元素第 1 行取第 1 个元素以此类推。数据来源的三种方式方式写法说明字面量数组{{[{...}, {...}]}}静态数据适合原型设计查询结果{{queries.restapi1.data.data}}最常见的动态数据源JS 表达式{{queries.users.data.map(u ({...u, fullName: u.first u.last}))}}对查询结果做二次加工组件配置 listview.js 对data的校验 schema 是「对象数组」或「字符串数组」的联合类型默认值为[{text: Sample text 1}]——即使留空组件也有一个可渲染的模板数据。三、属性详解PropertiesList View 的全部属性在属性面板中可配置下表整理了官方属性与源码中的默认值见 listview.js属性说明期望值源码默认值List data要展示的数据对象数组或返回对象数组的查询对象数组 / 查询[{text: Sample text 1}]Mode布局模式List单列列表或Grid多列网格list/gridlistShow bottom border是否显示每行底部分隔线仅List模式可用true/falsetrueColumnsGrid 模式下的列数仅Grid模式可用任意数值3Row height每行高度像素1–100 之间的数值100Enable pagination是否启用分页true/falsefalseRows per page每页行数仅启用分页后可用任意数值10分页的底层实现从 Listview.jsx 源码可以看到分页是前端切片实现的const startIndexOfRowInThePage currentPage 1 ? 0 : currentPage * rowPerPageValue - rowPerPageValue; const endIndexOfRowInThePage startIndexOfRowInThePage rowPerPageValue; const filteredData _.isArray(data) ? enablePagination ? data.slice(startIndexOfRowInThePage, endIndexOfRowInThePage) : data : [];即enablePagination为true时组件按rowsPerPage对数据做slice分页rowsPerPage会被强制转成数值Number(rowsPerPage) ? rowsPerPage || 10 : 10非法输入回退到 10。启用分页后组件底部会渲染一个 Pagination 控件且组件自身高度会预留约 54px 给分页栏。Grid 模式与行高Grid 模式下每行子容器宽度为100 / columns百分比见 ListviewSubcontainer.jsx列数小于 1 时会被强制修正为 1setPositiveColumnsRow height直接作用于每行子容器的高度height: rowHeight px超出部分overflow: hiddenList 模式下每行宽度为 100%showBorder为true时在行底绘制1px solid var(--cc-default-border)分隔线。附加行为属性除上述属性外源码中还定义了以下行为开关位于 Additional Actions 区Loading statetrue时组件显示 Spinner 加载动画等待数据就绪Listview.jsxDynamic heighttrue时行高随内容自适应仅在运行态生效并会清理行模板的临时布局缓存Visibility控制组件可见性Collapse when hidden隐藏时是否折叠占位Disable锁定组件禁用交互通过data-disabledinert同时阻断鼠标事件与键盘 Tab 焦点Tooltip悬停提示支持 Plain text / Markdown / HTML 三种格式见 listview.js。四、事件Events为 List View 添加事件处理器点击组件句柄打开右侧属性面板 → 进入Events区 → 点击Add handler。List View 提供两个事件Row clicked已弃用任意一行被点击时触发可定义多个动作。触发后通过selectedRowId、selectedRow两个变量暴露被点击行的信息详见下方暴露变量。:::warning 弃用提醒Row clicked事件已标记为 deprecated官方推荐改用Record clicked事件。 :::Record clicked推荐与 Row clicked 行为一致点击行内任意记录时触发并通过selectedRecordId、selectedRecord暴露数据。从源码 Listview.jsx 看点击处理统一由onRecordOrRowClicked(index)完成它同时设置selectedRecordId/selectedRecord/selectedRowId/selectedRow四组暴露变量并依次触发fireEvent(onRecordClicked)与fireEvent(onRowClicked)。事件定义见 listview.js。值得注意的是点击发生在捕获阶段onClickCapture见 ListviewSubcontainer.jsx因此即便行内子组件自身有点击处理器List View 的行点击事件也会先行触发。当选中行内的子组件数据后续更新时listViewComponentSlice.js 还会自动同步刷新selectedRecord/selectedRow的快照避免出现点击后数据滞后一行的问题。关于可用动作Actions的完整说明请查阅文档站点的 Action Reference 分类文档。Component Specific ActionsCSA目前 List View尚未实现组件级专属动作CSA无法通过 JS 查询直接调用如components.listview1.reset()之类的控制方法——对子组件的控制需通过下文第七节的children变量实现。五、暴露变量Exposed VariablesList View 暴露给全局 JS 作用域的变量如下组件实例名假设为listview1变量说明访问方式data存储加载到组件中的数据按行索引组织{{components.listview1.data[0].text1.text}}selectedRowId已弃用被点击行的 ID从0开始{{components.listview1.selectedRowId}}selectedRow已弃用被点击行内各组件的数据{{components.listview1.selectedRow.text1}}selectedRecordId被点击记录的 ID从0开始{{components.listview1.selectedRecordId}}selectedRecord被点击记录内各组件的数据{{components.listview1.selectedRecord.text1}}children所有记录内子组件的数据数组用于通过 JS 控制子组件见第七节data 与 children 的生成原理这两个变量的内容并非手动维护而是由 store 层 listViewComponentSlice.js 的deriveListviewExposedData自动派生遍历 List View 的直接子组件把每个子组件在当前行的暴露值收集为rowData对象键为子组件名称值为{...暴露值, id: 子组件uuid}写入结构components.listview1.children[rowIndex]与components.listview1.data[rowIndex]其中data是经过deepClone并剥离函数后的纯数据副本——这也是data变量适合被其他组件/查询读取的原因每次派生后同步触发依赖更新updateDependencyValues保证引用了components.listview1.data的表达式实时重算。该实现同样支持嵌套 List View子列表的暴露值通过outerIndices沿外层行索引定位如components.listview1[0].children表示第 0 行内的嵌套列表并能正确处理多层嵌套链_deriveListviewChain。行级作用域Row Scope机制listItem绑定与{{components.xxx.value}}行内引用之所以能各取所需得益于 listViewComponentSlice.js 中的prepareRowScope/updateRowScope行内子组件如复选框的暴露值以按行数组存储components[checkbox-uuid] [{value:false},{value:true},...]解析表达式时引擎用Object.create(components)创建一个以全局组件表为原型的作用域覆盖对象仅对 List View 的后代组件覆盖为当前行那一项scoped[childId] val[rowIndex]于是{{components.checkbox1.value}}在行 2 内解析到的是{value: true}而不是整个数组。这也解释了为什么同一 List View 内每行的表达式互不干扰。六、通用属性与样式Tooltip在General折叠区设置 Tooltip 的字符串内容鼠标悬停时即显示提示。源码中该配置支持Plain text/Markdown/HTML三种渲染格式tooltipFormat默认Plain text。Devices响应式属性说明期望值Show on desktop桌面端是否显示组件开关按钮或用fx配置逻辑表达式Show on mobile移动端是否显示组件开关按钮或用fx配置逻辑表达式Styles样式样式说明Background color背景色支持 Hex 色值或取色器源码默认var(--cc-surface1-surface)跟随主题的表面色Border color边框颜色默认var(--cc-weak-border)Visibility可见性仅接受布尔值{{true}}/{{false}}默认{{true}}Disable禁用组件仅接受布尔值默认{{false}}Border radius圆角仅接受 1–100 的数值源码默认6此外源码还定义了Box shadow默认0px 0px 0px 0px #00000040样式项。:::info 任何带fx按钮的属性都支持编程式配置——点击 fx 后输入{{表达式}}即可在运行态动态取值。 :::七、控制子组件Controlling Child Components所有行内子组件都通过children变量暴露它是一个按记录索引的数组每个元素对应一条记录内各子组件的数据。你可以用 JS 查询JavaScript Query控制行内子组件例如禁用第一条记录里的button1components.listview1.children[0].button1.disable(true) // 禁用第 1 条记录中的 button1:::caution 适用前提 只有实现了组件专属动作CSA的子组件才能通过 JS 查询控制。判断某组件是否支持 CSA请查阅对应组件的文档组件总览。 :::对于支持 CSA 的组件如按钮的disable/enable/setVisibility等这一机制让你可以按记录粒度批量操作行内组件——这是 List View 相比普通容器最强大的动态能力之一。八、完整实操从 REST API 渲染用户列表下面复现官方示例演示一个完整的 List View 数据流。第 1 步新建应用并拖入 List View新建应用从左侧组件面板把 List View 拖到画布上此时它处于空列表状态自带 Image/Text/Button 模板行第 2 步创建 REST API 查询新建查询数据源选择REST API方法选GET端点填https://reqres.in/api/users?page1。保存并运行查询在左侧查看结果可以看到返回的data对象里是一个对象数组每项含avatar、first_name、email等字段第 3 步绑定 List data编辑 List View 的List data属性用 JS 从查询取数{{queries.restapi1.data.data}}这里第一个data是restapi1查询的返回结果第二个data才是结果中真正承载对象数组的字段。绑定后组件会按数组长度自动生成对应行数的实例第 4 步设计行模板把组件文本、图片、按钮等嵌套进第一行后续行会自动按第一行的样式复制。行内组件通过listItem取当前行数据{{listItem.avatar}} // 示例展示头像图片 {{listItem.first_name}} // 示例展示姓名后续每行会自动套用第一行的布局与数据绑定:::tip 在嵌套组件上使用{{listItem.key}}展示数据其中key是查询结果对象中的字段名。例如示例中用{{listItem.avatar}}显示头像因为avatar是接口返回对象中的键。 :::九、源码级注意事项与最佳实践数据形态校验List data的 schema 要求数组元素为对象或字符串listview.js。如果查询返回的不是数组例如{ data: [...] }结构请像示例一样补一层.data取到数组本身行数变化自动同步当过滤后的数据行数变化时Listview.jsx 会通过initExposedValueArrayForChildren为所有子组件初始化/裁剪对应行数的暴露值槽位并清理children/data中的过期行因此不需要手动管理行数大列表性能行内组件解析采用行级作用域 惰性行索引机制isLazyResolvableParent/getLazyRowIndices见 componentsSlice.jsTable 的可展开行等场景只解析模板行与当前需要的行其余按需解析对普通大列表建议配合分页使用嵌套场景List View 支持在行内再嵌套 List ViewlistItem与暴露变量会按外层索引正确隔离多级表达式如{{listItem.orders}}配合内层listItem即可实现主子表结构事件选择新应用请直接使用Record clickedRow clicked仅为向后兼容保留事件定义中明确标注(Deprecated)组件约束Calendar / Kanban 不可拖入 List View行内组件的 CSA 控制能力取决于该组件自身的实现。十、相关文档与源码索引组件官方文档listview.md另有 version-3.0.0-LTS 版本 可对照差异组件配置与默认值listview.js组件运行时实现Listview.jsx、ListviewSubcontainer.jsx、listview.scss暴露变量派生与行级作用域listViewComponentSlice.jslistItem解析与惰性行解析componentsSlice.js相关测试可参考仓库frontend与cypress-tests目录下针对 List View 的用例验证分页、事件与数据绑定行为。【免费下载链接】ToolJetOpen-source foundation of ToolJet AI - the enterprise app generation platform for internal tools, dashboards, business applications, workflows and AI agents. Build visually, from a prompt, or from Claude Code, Codex and Cursor over MCP 项目地址: https://gitcode.com/GitHub_Trending/to/ToolJet创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考