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

11 KiB
Raw Blame History

Bricks UI Framework - Popup 组件技术文档


概述

bricks.Popup 是基于 bricks.VBox 的弹窗组件,用于创建可浮动、可移动、可调整大小的模态或非模态对话框。它支持自动打开/关闭、点击外部区域自动关闭、内容动态加载等功能。

此外,框架还提供了两个扩展类:

  • bricks.PopupWindow:带标题栏和控制按钮(最小化、全屏、关闭)的窗口式弹窗。
  • bricks.WindowsPanel:用于管理多个最小化的窗口列表面板。

该组件适用于构建现代化 Web 应用中的对话框、提示框、应用窗口等交互界面。


全局命名空间初始化

var bricks = window.bricks || {};

确保 bricks 命名空间存在,避免覆盖已有对象。


默认配置方法

bricks.get_popup_default_options()

返回一个包含默认选项的对象,供 Popup 使用。

返回值

{
  timeout: 0,
  archor: 'cc',
  auto_open: true,
  auto_dismiss: true,
  auto_destroy: true,
  movable: true,
  resizable: false,
  modal: true
}
参数 类型 描述
timeout Number 自动关闭延迟时间(秒),设为 0 表示不自动关闭
archor String 定位锚点,取值见下表
auto_open Boolean 是否在实例化后自动打开弹窗
auto_dismiss Boolean 是否允许点击外部区域关闭弹窗
auto_destroy Boolean 关闭后是否自动销毁组件
movable Boolean 是否可拖动
resizable Boolean 是否可调整大小
modal Boolean 是否为模态(遮罩其他控件)

archor 取值说明
支持九宫格定位:
'tl', 'tc', 'tr', 'cl', 'cc', 'cr', 'bl', 'bc', 'br'
分别表示:左上、中上、右上、左中、居中、右中、左下、中下、右下


核心类:bricks.Popup

继承自 bricks.VBox,提供完整的弹窗功能。

构造函数:constructor(opts)

参数

  • opts (Object): 配置选项,合并默认配置使用。

内部属性初始化

属性 类型 初始值 说明
no_opened Boolean true 是否首次打开
auto_task Task null 超时任务句柄
issub Boolean false 是否依附于某个控件显示
opened Boolean false 当前是否已打开
content_box VBox 实例 内容容器
content_w Widget content_box 内容承载部件
moving_w Widget this 可拖动目标(默认整个弹窗)
target_w Widget bricks.Body 目标绑定控件
moving_status Boolean false 拖拽状态标志
resize_status Boolean false 缩放状态标志

初始化流程

  1. 设置 CSS 类名为 popup
  2. 将自身置于顶层z-index
  3. 创建内容容器并添加到内部
  4. 绑定点击外部关闭事件(若启用 auto_dismiss
  5. 启用拖动(movable)与缩放(resizable
  6. 默认隐藏(display: none
  7. 添加至 Body 容器
  8. 绑定点击以提升层级
  9. auto_open === true,调用 open()
  10. 若有 content,监听 opened 事件加载内容

方法详解

load_content() → Promise<void>

异步加载配置中的 content 并渲染到内容区。

async load_content(){
  var w = await bricks.widgetBuild(this.content, this);
  if (w){
    this.set_dismiss_events(w);
    this.content_w.clear_widgets();
    this.content_w.add_widget(w);
  }
}

⚠️ 依赖 bricks.widgetBuild() 动态构建子控件树。


set_dismiss_events(widget)

为指定控件绑定关闭事件。

this.dismiss_events.forEach(ename => {
  w.bind(ename, this.destroy.bind(this));
});

示例:dismiss_events: ['ok', 'cancel'] 会绑定这些事件触发销毁。


bring_to_top()

将当前弹窗置顶(最高 z-index更新全局 toppopup 引用。

this.zindex = bricks.app.new_zindex();
this.set_style('zIndex', this.zindex);
bricks.app.toppopup = this;

popup_from_widget(from_w)

从指定控件位置智能定位弹窗(避开屏幕边缘)。

算法逻辑
  • 计算源控件中心坐标 (ox, oy)
  • 若源在左侧,则弹窗出现在右侧;否则出现在左侧
  • 若源在上方,则弹窗出现在下方;否则出现在上方
  • 边界检测防止溢出屏幕

适用于 Tooltip 或 Context Menu 场景。


setup_resizable()

启用可缩放功能,在右下角添加 SVG 缩放手柄。

子组件
  • resizable_w: SVG 图标(右下三角)
事件绑定
  • mousedownresize_start_pos
  • mousemoveresizing
  • mouseupstop_resizing

resize_start_pos(e)

记录初始尺寸和鼠标位置,开始缩放。

this.s_width = rect.width;
this.s_height = rect.height;
this.s_offsetX = e.clientX;
this.s_offsetY = e.clientY;

resizing(e)

实时调整宽度和高度。

cx = this.s_width + e.clientX - this.s_offsetX;
cy = this.s_height + e.clientY - this.s_offsetY;
this.set_style('width', cx + 'px');
this.set_style('height', cy + 'px');

stop_resizing(e)

结束缩放操作,解绑全局事件。

this.resize_status = false;
bricks.Body.unbind('mousemove', this.resizing.bind(this));
bricks.Body.unbind('mouseup', this.stop_resizing.bind(this));

positify_tl()

根据 archor 和屏幕尺寸计算并设置弹窗位置。

尺寸解析优先级
  1. cwidth / cheight(字符单位 × 字符大小)
  2. width / height(百分比或 px
  3. 默认占屏 80%
锚点布局规则
第一位(垂直) 第二位(水平)
t: 顶部对齐 l: 左对齐
c: 居中 c: 居中
b: 底部对齐 r: 右对齐

返回 { top, left } 像素坐标。


setup_movable()

启用拖动功能,绑定 mousedowntouchstart


rec_start_pos(e)

记录拖动起点偏移量,并绑定移动与释放事件。

this.offsetX = e.clientX - rect.left;
this.offsetY = e.clientY - rect.top;

moving(e)

实时更新位置。

cx = e.clientX - this.offsetX;
cy = e.clientY - this.offsetY;
this.set_style('left', cx + 'px');
this.set_style('top', cy + 'px');

stop_moving(e)

停止拖动,解绑所有相关事件。


click_outside(event)

点击弹窗外区域时关闭弹窗(仅当 auto_dismisstrue 时生效)。

if (event.target != this.dom_element) this.dismiss();

open()

打开弹窗。

流程
  1. 若无父节点,加入 app 根容器
  2. 若是首次打开:
    • 设置目标控件(widget 参数)
    • 执行定位 positify_tl()
  3. 显示元素(display: block
  4. 触发 opened 事件
  5. 设置超时关闭任务(如需)
  6. 若为模态,则禁用目标控件
  7. 提升至顶层

dismiss()

关闭弹窗。

流程
  1. 若为模态,恢复目标控件可用状态
  2. 清除超时任务
  3. 隐藏元素(display: none
  4. 触发 dismissed 事件
  5. auto_destroy === true,执行 destroy()

destroy()

彻底销毁组件。

if (this.opened) this.dismiss();
if (this.parent) {
  this.parent.remove_widget(this);
  this.parent = null;
}

add_widget(w, i)

向内容区域添加控件,并自动绑定关闭事件。

auto_opentrue,则立即打开弹窗。


remove_widget(w) / clear_widgets()

代理调用 content_w 的对应方法。


扩展类:bricks.PopupWindow

继承自 Popup,模拟操作系统窗口,带有标题栏和控制按钮。

构造函数特点

opts.movable = true;
opts.resizable = true;
opts.auto_open = false; // 手动控制打开时机

特有属性

属性 说明
title_bar 标题栏容器HBox
tb_w 控制按钮栏IconBar
content_w 主内容区Layout
title_w 标题文本显示控件

内部结构

  1. 标题栏 (titlebar)
    • 图标SVG
    • 控制按钮组(删除、最小化、全屏)
    • 标题文本
  2. 填充层 (Filler)
    • 包含主内容区
  3. 内容区 (Layout)
    • 支持 Flex 布局

控制按钮功能

按钮 功能
delete 调用 destroy() 销毁窗口
minimize 调用 win_minimize() 最小化
fullscreen 进入全屏模式

win_minimize()

关闭窗口并将自身推入 bricks.app.mwins 数组,供后续恢复。

this.dismiss();
if (!this.auto_destroy) {
  bricks.app.mwins.push(this);
}

set_title(txt)

动态修改窗口标题。

this.title_w.set_text(txt);

工具类:bricks.WindowsPanel

用于展示所有最小化的窗口列表,点击可恢复。

构造函数行为

  • 固定宽高为 80%
  • 自动关闭、销毁
  • 不自动打开

数据绑定结构

使用 Cols 组件渲染表格:

{
  "total": 3,
  "rows": [
    { "title": "Settings", "url": "...", "pos": 0 },
    ...
  ]
}

每行包含图标、标题,点击触发 del_window()


del_window(event)

恢复指定位置的窗口并从列表中移除。

var pos = event.params.pos;
var w = bricks.app.mwins[pos];
w.open(); // 恢复显示
bricks.app.mwins.splice(pos, 1); // 删除记录
this.dismiss(); // 关闭面板

工厂注册

bricks.Factory.register('Popup', bricks.Popup);
bricks.Factory.register('PopupWindow', bricks.PopupWindow);

支持通过字符串类型动态创建组件实例。


静态辅助函数

bricks.get_popupwindow_default_options()

返回专用于 PopupWindow 的默认配置,与普通 Popup 的区别在于:

+ resizable: true

其余同 get_popup_default_options()


使用示例

创建简单弹窗

let popup = new bricks.Popup({
  content: {
    widgettype: 'Text',
    options: { text: 'Hello World!' }
  },
  archor: 'cc',
  timeout: 3000
});

创建应用窗口

let win = new bricks.PopupWindow({
  title: '用户设置',
  icon: '/icons/settings.svg',
  content: { ... },
  auto_open: true
});

显示窗口管理器

let panel = new bricks.WindowsPanel();
panel.open();

注意事项

  1. 事件作用域问题:大量使用 .bind(this),注意性能影响。
  2. 内存泄漏风险:未正确解绑事件可能导致残留监听器。
  3. 触摸设备兼容性:支持 touchstart/move/end,但需测试跨平台表现。
  4. z-index 管理:依赖 bricks.app.new_zindex(),需保证唯一递增。
  5. 异步内容加载load_content() 为异步,注意加载顺序。

总结

bricks.Popup 系列组件提供了强大而灵活的弹窗系统,具备以下核心能力:

模态/非模态切换
自动定位与边界适配
拖拽移动 & 缩放
外部点击关闭
超时自动关闭
内容动态加载
窗口最小化管理

适合构建复杂的桌面风格 Web 应用界面。


文档版本v1.0
最后更新2025-04-05