# `DynamicAccordion` 技术文档 > **模块名称:** `bricks.DynamicAccordion` > **继承自:** `bricks.VScrollPanel` > **用途:** 动态可折叠列表组件,支持分页加载、内容动态渲染、编辑操作(增删改)、工具栏扩展等高级功能。 --- ## 目录 - [1. 概述](#1-概述) - [2. 核心类结构](#2-核心类结构) - [2.1 `bricks.AccordionItem`](#21-bricksaccordionitem) - [2.2 `bricks.AccordionInfo`](#22-bricksaccordioninfo) - [2.3 `bricks.DynamicAccordion`](#23-bricksdynamicaccordion) - [3. 配置选项 (`opts`)](#3-配置选项-opts) - [4. 生命周期与构建流程](#4-生命周期与构建流程) - [5. 主要方法说明](#5-主要方法说明) - [5.1 渲染控制](#51-渲染控制) - [5.2 内容生成](#52-内容生成) - [5.3 数据处理与分页](#53-数据处理与分页) - [5.4 编辑功能](#54-编辑功能) - [5.5 事件系统](#55-事件系统) - [6. CSS 类名约定](#6-css-类名约定) - [7. 使用示例](#7-使用示例) - [8. 注意事项](#8-注意事项) --- ## 1. 概述 `bricks.DynamicAccordion` 是一个基于 `VScrollPanel` 的高级可折叠面板组件,用于展示大量条目数据。每个条目由标题区域和可展开的内容区组成,支持: - 分页异步加载数据 - 可配置的记录视图模板(`record_view`) - 展开后动态加载详细内容(`content_view`) - 行内工具栏(支持自定义按钮及编辑操作) - 增删改查(CRUD)交互支持 - 条件性内容显示(依赖字段值) 适用于需要高效展示并操作大量结构化数据的场景,如后台管理界面中的日志、订单、用户列表等。 --- ## 2. 核心类结构 ### 2.1 `bricks.AccordionItem` ```js class extends bricks.VBox ``` 表示单个可折叠项的容器,包含两个子部件: - `AccordionInfo`:点击触发展开/收起的头部 - `VBox`:隐藏的内容区域(默认不显示) #### 构造函数 ```js constructor(opts) { super(opts); this.set_css('accordion-item'); } ``` #### 特性 - 自动添加 CSS 类 `accordion-item` - 继承 `VBox` 布局特性(垂直排列) --- ### 2.2 `bricks.AccordionInfo` ```js class extends bricks.FHBox ``` 代表折叠项的标题部分,通常用于显示摘要信息,并绑定点击事件以切换内容可见性。 #### 构造函数 ```js constructor(opts) { super(opts); this.set_css('accordion-item-info'); } ``` #### 特性 - 使用 `FHBox` 实现水平布局 - 添加 CSS 类 `accordion-item-info` - 存储关联的数据记录在 `user_data` 属性中 --- ### 2.3 `bricks.DynamicAccordion` 主控件类,负责整体逻辑调度、数据加载、UI 构建与交互响应。 ```js class extends bricks.VScrollPanel ``` #### 注册方式 ```js bricks.Factory.register('DynamicAccordion', bricks.DynamicAccordion); ``` 允许通过工厂方法创建实例: ```js bricks.createWidget("DynamicAccordion", {...}); ``` --- ## 3. 配置选项 (`opts`) | 参数 | 类型 | 说明 | |------|------|------| | `data_url` | String | 获取数据的 API 地址 | | `data_method` | String (可选) | 请求方法,默认为 `'GET'` | | `data_params` | Object (可选) | 发送请求时附加的参数 | | `cache_limit` | Number (可选) | 缓存页数上限 | | `page_rows` | Number (可选) | 每页返回的行数 | | `row_cheight` | Number (可选, 默认: `1.5`) | 每行高度倍率(影响布局计算) | | `record_view` | Widget 描述对象 | 定义每行摘要区域的 UI 结构 | | `content_rely_on` | String (可选) | 控制是否展开内容的字段名 | | `content_rely_value` | Any (可选) | 上述字段应匹配的值才能展开内容 | | `editable` | Object (可选) | 启用编辑模式的相关配置 | |   `.add_icon`, `.update_icon`, `.delete_icon` | String | 图标路径或资源引用 | |   `.form_cheight` | Number | 表单高度系数 | |   `.new_data_url`, `.update_data_url`, `.delete_data_url` | String | 对应操作的提交 URL | | `fields` | Array\ | 字段定义数组,用于表单和列头渲染 | | `record_toolbar` | Object (可选) | 自定义行工具栏按钮配置 | | `record_toolbar_collapsable` | Boolean (可选) | 工具栏是否可折叠(未完全实现) | | `header` | Object (可选) | 头部固定行配置(暂未启用) | | `content_view` | Widget 描述对象 | 展开后显示的详情内容模板 | | `title` | String (可选) | 页面标题文本(i18n 支持) | | `description` | String (可选) | 页面描述文本 | > ⚠️ 所有字符串文本均支持国际化(`i18n: true`)。 --- ## 4. 生命周期与构建流程 `build_all()` 方法是初始化入口,在构造完成后延迟执行(`schedule_once(..., 0.1)`): ```js async build_all() { if (this.title) this.build_title(); if (this.description) this.build_description(); await this.build_toolbar(); await this.build_header(); this.container = new bricks.VScrollPanel({}); this.add_widget(new bricks.Filler().add_widget(this.container)); this.container.bind('min_threshold', this.load_previous_page.bind(this)); this.container.bind('max_threshold', this.load_next_page.bind(this)); await this.render(); } ``` ### 流程图解: ``` [初始化] ↓ build_title() → 添加标题 build_description() → 添加描述 build_toolbar() → 添加全局工具栏 build_header() → 创建表头(模拟) ↓ 创建内部容器 container (VScrollPanel) ↓ 绑定滚动触底/触顶事件 → 分页加载 ↓ render() → 加载并渲染第一页数据 ``` --- ## 5. 主要方法说明 ### 5.1 渲染控制 #### `render(params)` 根据参数重新加载数据并刷新 UI。 - 若参数未变,则跳过 - 调用 `loader.loadData(params)` 获取数据 - 成功后调用 `dataHandle(d)` #### `dataHandle(d)` 处理服务器返回的数据包: ```js { rows: [...], // 当前页数据 add_page: 2, // 新增页码 delete_page: 1 // 应删除的旧页码(超出缓存限制) } ``` 调用 `renderAccordionItems(data, page)` 渲染新项,并清理过期页。 --- ### 5.2 内容生成 #### `build_item(record)` 构建单个可折叠项: - 创建 `AccordionItem` - 调用 `build_info(item, record)` 构建标题区 - 创建隐藏的 `content` 区域 - 绑定点击事件:`line_clicked(info, content, record)` - 返回完整 `item` 若 `record === null`,则作为“表头”使用。 #### `build_info(item, record)` 生成标题区域 UI: - 使用 `widgetBuild(this.record_view, info, record)` 渲染摘要内容 - 插入 `record_toolbar`(含编辑图标) - 设置 `info.user_data = record` - 返回 `AccordionInfo` 实例 当无 `record` 时,用于生成列头标签。 --- ### 5.3 数据处理与分页 #### `load_previous_page() / load_next_page()` 滚动接近边界时自动加载前后页: - 显示加载动画(`Running` 提示) - 设置 `this.loading = true` 防止重复请求 - 调用 `loader.loadPreviousPage()` 或 `loadNextPage()` - 成功后调用 `dataHandle()` 并恢复滚动位置 - 错误捕获并输出调试日志 #### `delete_page(page)` 移除指定页的所有 DOM 元素: ```js querySelectorAll('[data-page="X"]') → 移除对应 widget ``` 确保内存和 DOM 不泄漏。 --- ### 5.4 编辑功能 #### 新增记录 - `add_record(info)`:打开内嵌表单 - `add_record_abort()`:取消新增 - `add_record_finish()`:提交成功后刷新列表 #### 更新记录 - `update_record(info, record)`:弹出编辑表单 - `update_cancel()`:取消编辑 - `update_record_finish()`:保存后更新视图或提示 #### 删除记录 - `delete_record(info, record)`:弹出确认框 - `delete_record_act()`:发送删除请求,删除成功则移除该项 #### 新建表单快捷入口 - `build_new_form()`:顶部添加“+”按钮和隐藏表单 - 点击按钮展开/收起新建表单 - 提交后自动调用 `render()` 刷新列表 --- ### 5.5 事件系统 #### 内部事件绑定 - `info.bind('click', line_clicked)`:行点击展开内容 - `IconBar` 工具按钮绑定各种事件(`add`, `update`, `delete`) - 自定义工具按钮通过 `fire_event(name, data)` 派发事件 #### 外部可监听事件 | 事件名 | 触发时机 | 参数 | |--------|----------|------| | `row_selected` | 用户点击某一行 | `info` widget | | `conformed` | 删除确认后 | —— | | `submited` | 表单提交成功 | 响应对象 | | `[custom_tool_name]` | 自定义工具按钮被点击 | `record` 数据 | 可通过 `bind(event, handler)` 监听。 --- ## 6. CSS 类名约定 | 类名 | 作用 | |------|------| | `.accordion-item` | 整个折叠项外层容器 | | `.accordion-item-info` | 折叠项标题区域 | | `.accordion-item-info-selected` | 当前行被选中状态 | | `.accordion-item-content` | 内容区域样式基类 | | `.filler` | 占位填充容器(用于自适应高度) | 建议配合 SCSS 定义主题风格,例如圆角、阴影、过渡动画等。 --- ## 7. 使用示例 ```js var accordion = new bricks.DynamicAccordion({ title: "User List", description: "Manage all registered users.", data_url: "/api/users", page_rows: 10, cache_limit: 5, fields: [ { name: "name", label: "Name" }, { name: "email", label: "Email" }, { name: "status", label: "Status" } ], record_view: { widgettype: "HBox", options: { cheight: 1.5 }, subwidgets: [ { widgettype: "Text", options: { otext: "{{name}}" } }, { widgettype: "Text", options: { otext: "{{email}}", halign: "right" } } ] }, content_view: { widgettype: "Form", options: { fields: [ { name: "name", uitype: "text" }, { name: "email", uitype: "email" }, { name: "bio", uitype: "textarea" } ] } }, editable: { form_cheight: 8, new_data_url: "/api/users/create", update_data_url: "/api/users/update", delete_data_url: "/api/users/delete", add_icon: "/static/icons/add.svg" }, record_toolbar: { tools: [ { name: "view_logs", tip: "View operation logs", icon: "/icons/logs.svg" } ] } }); // 监听自定义操作 accordion.bind("view_logs", function(record){ console.log("查看日志:", record); }); ``` --- ## 8. 注意事项 1. **性能优化** - 支持分页缓存,避免一次性加载过多数据 - 滚动加载机制减少初始等待时间 - `cache_limit` 应合理设置以防内存占用过高 2. **内容懒加载** - `content_view` 仅在点击展开时构建,节省资源 - 再次点击会清除内容(`clear_widgets()`),防止状态残留 3. **国际化支持** - 所有文本建议使用 `otext` + `i18n: true` 配合语言包 4. **DOM 清理** - 删除页面时主动移除 widgets 和事件监听(依赖框架 GC) 5. **扩展性** - 可通过 `record_toolbar` 添加自定义操作按钮 - `fire_event()` 支持插件式开发 6. **兼容性** - 依赖 `bricks.PageDataLoader`, `bricks.HttpJson`, `bricks.widgetBuild` 等基础模块 - 需确保这些模块已正确加载 --- ✅ **推荐搭配组件:** - `bricks.Form`:用于编辑表单 - `bricks.Conform`:删除确认对话框 - `bricks.Running`:加载指示器 - `bricks.IconBar`:工具栏按钮组 📦 此组件适合集成于管理系统、数据看板等复杂前端应用中。