bricks/docs/cn.old/layout.md
2025-11-19 12:30:39 +08:00

359 lines
10 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# `bricks.Layout` 及其子类技术文档
本技术文档详细描述了 `bricks.Layout` 类及其相关布局组件(如 `VBox`, `HBox`, `Filler`, `ResponsableBox` 等)的功能、结构和使用方式。这些类是基于 `bricks.JsWidget` 构建的 UI 容器组件,支持键盘导航、动态内容管理与响应式布局。
---
## 目录
- [概述](#概述)
- [核心模块](#核心模块)
- [`bricks.Layout`](#brickslayout)
- [`bricks.VBox`](#bricksvbox)
- [`bricks.HBox`](#brickshbox)
- [`bricks.FHBox`](#bricksfhbox)
- [`bricks.FVBox`](#bricksfvbox)
- [`bricks.Filler`](#bricksfiller)
- [`bricks.ResponsableBox`](#bricksresponsablebox)
- [键盘选择机制](#键盘选择机制)
- [事件处理](#事件处理)
- [方法说明](#方法说明)
- [工厂注册](#工厂注册)
- [示例用法](#示例用法)
---
## 概述
`bricks` 是一个前端 UI 组件框架,`Layout` 是其基础容器类用于组织和管理子控件widgets。所有布局类均继承自 `bricks.Layout`,并可通过 CSS 类实现水平或垂直排列。此外,该系统支持**键盘导航**,允许用户通过方向键在可聚焦元素之间切换,并通过 Enter 键触发操作。
主要特性包括:
- 支持嵌套布局结构
- 提供标题、描述、工具栏构建方法
- 内置键盘导航支持(上下左右 + Enter
- 基于栈的层级导航机制
- 动态添加/删除子控件
- 响应式设计支持(`ResponsableBox`
---
## 核心模块
### `bricks.Layout`
#### 继承关系
```js
class Layout extends bricks.JsWidget
```
#### 属性
| 属性名 | 类型 | 描述 |
|-------|------|------|
| `_container` | Boolean | 标记为容器组件 |
| `keyselectable` | Boolean | 是否启用键盘选择功能 |
| `children` | Array | 子控件列表 |
| `selected_item` | Widget | 当前选中的子控件 |
| `title` | String (可选) | 容器标题文本 |
| `description` | String (可选) | 描述文本 |
| `toolbar` | Object (可选) | 工具栏配置对象 |
| `use_key_select` | Boolean (可选) | 初始化时是否自动启用键盘选择 |
> ⚠️ 注意:`use_key_select` 在代码中未明确定义于构造函数参数,但被条件判断引用,建议作为选项传入。
#### 构造函数
```js
constructor(options)
```
- **参数**
- `options` `{Object}` 配置项,支持以下字段:
- `title`: 显示标题
- `description`: 显示描述
- `toolbar`: 工具栏配置
- `keyselectable`: 是否允许键盘选择(默认 `false`
- `use_key_select`: 若为真,则自动调用 `enable_key_select()`
- **行为**
- 调用父类构造函数
- 初始化内部状态
- 若设置了 `use_key_select`,则立即启用键盘选择模式
---
### `bricks.VBox`
垂直布局容器,子元素垂直堆叠。
```js
class VBox extends Layout
```
- **构造函数**
- 自动设置 CSS 类:`vcontainer`
- **用途**:创建纵向排列的内容区域。
---
### `bricks.HBox`
水平布局容器,子元素水平排列。
```js
class HBox extends Layout
```
- **构造函数**
- 设置 CSS 类:`hcontainer`
- **用途**:横向排布控件。
---
### `bricks.FHBox`
固定行水平盒子(不换行)。
```js
class FHBox extends HBox
```
- **构造函数**
- 调用 `super(options)`
- 设置样式:`flexWrap: 'nowrap'`
- **用途**:确保子元素始终在同一行显示。
---
### `bricks.FVBox`
固定列垂直盒子(不换行)。
```js
class FVBox extends VBox
```
- **构造函数**
- 设置样式:`flexWrap: 'nowrap'`
- **用途**:防止垂直方向上的内容换列(较少见,通常用于嵌套场景)。
---
### `bricks.Filler`
弹性填充占位符,常用于 Flex 布局中占据剩余空间。
```js
class Filler extends Layout
```
- **构造函数**
- 设置 CSS 类:`filler`
- 注释中包含潜在增强样式(如 `flexGrow: 1`),可用于扩展
- **用途**:在布局中插入空白区域以平衡界面。
---
### `bricks.ResponsableBox`
响应式布局容器,根据宽高比动态调整布局方向。
```js
class ResponsableBox extends Layout
```
- **事件绑定**
- 监听 `'element_resize'` 事件,自动调用 `reset_type()`
- **`reset_type(event)` 行为**
- 判断当前容器宽度与高度:
-`width > height` → 视为横向,应用 `hcontainer` 并设 `height: 100%`
- 否则 → 视为纵向,应用 `vcontainer` 并设 `width: 100%`
- 输出调试日志到控制台
> 💡 此类适合移动端或窗口缩放频繁的场景实现“自适应”UI 排列。
---
## 键盘选择机制
### 全局栈管理
```js
bricks.key_selectable_stack = [];
```
- 所有启用了键盘选择的 `Layout` 实例按进入顺序压入栈。
- 最顶层的实例才响应按键事件(通过 `is_currkeyselectable()` 判断)。
### 关键方法
| 方法 | 说明 |
|------|------|
| `enable_key_select()` | 启用键盘选择,注册事件监听,推入栈 |
| `disable_key_select()` | 停止监听,从栈顶弹出自身(若为当前层) |
| `is_currkeyselectable()` | 判断自己是否处于栈顶且可选 |
### 导航逻辑
| 键盘按键 | 功能 |
|--------|------|
| `ArrowDown` | 选择下一个子项(循环) |
| `ArrowUp` | 选择上一个子项(循环) |
| `ArrowRight` | 进入下一级(进入当前选中项的子菜单) |
| `ArrowLeft` | 返回上一级(退出当前层级) |
| `Enter` | 触发当前选中项的 `click` 事件 |
> 🔄 循环选择:到达末尾后回到开头,反之亦然。
---
## 事件处理
### `key_handler(event)`
主键盘事件处理器,仅当实例位于 `key_selectable_stack` 栈顶时生效。
- 使用 `event.key` 匹配方向键与回车
- 分发对应操作(上下选择、进出层级、确认)
### 生命周期事件
- `on_parent`:当控件被添加或移除父容器时派发,通知父子关系变更
---
## 方法说明
### 控件管理
| 方法 | 参数 | 描述 |
|------|------|------|
| `add_widget(w, index)` | `w`: widget, `index?`: number | 将控件插入指定位置或追加至末尾 |
| `remove_widget(w)` | `w`: widget | 移除指定控件,清理 DOM 和事件 |
| `clear_widgets()` | 无 | 清空所有子控件及 DOM 子节点 |
| `remove_widgets_at_begin(cnt)` | `cnt`: number | 移除前 `cnt` 个子控件 |
| `remove_widgets_at_end(cnt)` | `cnt`: number | 移除后 `cnt` 个子控件 |
> ✅ `insertBefore` / `appendChild` 被合理使用以维持 DOM 结构一致性。
---
### UI 构建方法
| 方法 | 功能 |
|------|------|
| `build_title()` / `build_title_widget()` | 创建并添加标题控件(`Title3` |
| `build_description()` / `build_description_widget()` | 添加描述文本(`Text` |
| `build_toolbar_widget(ext_tools)` | 构建浮动图标工具栏(`FloatTextIconBar` |
> 🔔 多数构建方法检查是否存在对应属性(如 `this.title`)后再创建。
---
### 选择控制方法
| 方法 | 功能 |
|------|------|
| `select_item(w)` | 选中指定控件,取消之前的选择 |
| `select_default_item()` | 默认选择第一个子控件 |
| `select_next_item()` | 向下循环选择 |
| `select_previous_item()` | 向上循环选择 |
| `find_first_keyselectable_child()` | 深度优先查找首个支持键盘选择的后代 |
---
### 层级跳转
| 方法 | 功能 |
|------|------|
| `down_level()` | 进入当前选中控件的子层级(需支持 keyselectable |
| `up_level()` | 退出当前层级,返回上级 |
> 🧭 类似菜单树导航模型,利用栈维护路径。
---
## 工厂注册
以下类型已向 `bricks.Factory` 注册,可用于声明式创建:
```js
bricks.Factory.register('HBox', bricks.HBox);
bricks.Factory.register('FHBox', bricks.FHBox);
bricks.Factory.register('VBox', bricks.VBox);
bricks.Factory.register('FVBox', bricks.FVBox);
bricks.Factory.register('Filler', bricks.Filler);
bricks.Factory.register('HFiller', bricks.Filler); // 水平填充
bricks.Factory.register('VFiller', bricks.Filler); // 垂直填充(同 Fillers
bricks.Factory.register('ResponsableBox', bricks.ResponsableBox);
```
> ✅ 支持模板引擎或 JSON 配置动态生成界面。
---
## 示例用法
### 创建带标题的垂直布局
```js
let vbox = new bricks.VBox({
title: "用户设置",
description: "请选择要修改的选项",
keyselectable: true
});
// 添加子控件
let btn1 = new bricks.Button({ otext: "个人资料" });
let btn2 = new bricks.Button({ otext: "安全设置" });
vbox.add_widget(btn1);
vbox.add_widget(btn2);
document.body.appendChild(vbox.dom_element);
```
### 启用手动键盘导航
```js
vbox.enable_key_select(); // 激活键盘控制
```
此时可用 ↑↓ 键切换按钮Enter 执行点击,← 返回上级(如果有)。
### 响应式容器示例
```js
let responsive = new bricks.ResponsableBox();
responsive.add_widget(new bricks.Label({ otext: "此布局会随尺寸变化!" }));
document.body.appendChild(responsive.dom_element);
```
窗口大小改变时,布局方向将自动调整。
---
## 注意事项与最佳实践
1. **避免重复启用 `keyselectable`**
- 确保 `enable_key_select()` 不被多次调用导致重复绑定事件
2. **手动管理栈结构风险**
- `key_selectable_stack` 是全局状态,跨组件交互需谨慎
3. **DOM 更新同步**
- 所有 `add_widget` / `remove_widget` 都应及时更新 DOM 和 `children` 数组
4. **性能优化建议**
- `find_first_keyselectable_child()` 使用递归,深层嵌套可能影响性能,可缓存结果
5. **i18n 支持**
- 所有文本控件启用 `i18n: true`,便于国际化
---
## 总结
`bricks.Layout` 提供了一个强大而灵活的基础布局系统,结合键盘导航与响应式能力,非常适合构建复杂的桌面风格 Web 应用界面(如仪表盘、菜单系统、表单布局等)。其模块化设计使得扩展新布局类型变得简单,同时工厂模式支持运行时动态渲染。
> ✅ 推荐在需要高可访问性Accessibility和键盘操作支持的应用中使用此组件体系。
---
📌 **版本信息**:本文档基于提供的 JavaScript 代码片段撰写
📅 **最后更新**2025年4月5日