17 KiB
Bricks.js 技术文档
Bricks.js 是一个轻量级的前端工具库,提供了一系列实用函数和类,用于处理 DOM 操作、事件监听、数据转换、网络请求、媒体流播放等常见任务。它支持响应式设计、动态组件构建,并兼容移动端与桌面端环境。
目录
- 初始化
- 核心配置
- 时间与格式化
- DOM 与观察者
- URL 与资源管理
- 数据处理与类型判断
- 颜色解析
- 异步与流式响应
- Blob 与 Base64 转换
- 表单与对象操作
- 调试系统
- 设备检测
- UI 定位与布局
- 扩展方法(Array)
- Cookie 操作
- 高度同步
- 深拷贝与对象操作
- 媒体流播放
- 模板渲染与组件构建
- 可观察对象 Observable
- 队列结构 Queue
- DOM 创建工具
初始化
var bricks = window.bricks || {};
确保 bricks 全局命名空间存在,避免覆盖已有变量。
核心配置
bricks.bug
- 类型:
boolean | string - 默认值:
false - 说明: 控制是否开启调试模式。
false: 不输出任何调试信息。true: 在控制台打印调用栈和参数。'server': 将日志发送到服务器/debug接口。
时间与格式化
bricks.timeDiff(startTime)
计算当前时间与指定时间之间的差值,并格式化为 HH:mm:ss.SSS 字符串。
参数
| 参数名 | 类型 | 说明 |
|---|---|---|
| startTime | Date | number |
开始时间(毫秒或 Date 对象) |
返回值
- 类型:
string - 格式:
"HH:mm:ss.SSS"
示例
const start = new Date() - 3661000; // 1小时1分钟1秒前
console.log(bricks.timeDiff(start)); // "01:01:01.000"
DOM 与观察者
bricks.resize_observer
使用 ResizeObserver 监听元素尺寸变化。
功能
- 自动触发绑定了
bricks_widget的组件的element_resize事件。 - 传递
contentRect作为事件参数。
使用方式
widget.dom_element.bricks_widget = widget;
bricks.resize_observer.observe(widget.dom_element);
bricks.dom_on_off_observer
使用 MutationObserver 监听 DOM 添加/移除事件。
触发事件
| 事件名 | 触发条件 |
|---|---|
domon |
元素被添加到 DOM |
domoff |
元素从 DOM 移除(包括后代) |
配置
- 监听
document.body - 启用
childList和subtree,深度遍历所有子节点。
注意事项
- 只处理元素节点(Node Type === 1)
- 支持嵌套组件自动解绑
URL 与资源管理
addParamsToUrl(url, params, widget)
向 URL 添加查询参数,支持相对路径。
参数
| 参数 | 类型 | 说明 |
|---|---|---|
| url | string | 原始 URL(相对或绝对) |
| params | object | 要添加的键值对参数 |
| widget | any | (未使用,保留字段) |
返回值
- 类型:
string - 包含新参数的完整 URL
示例
addParamsToUrl('/api/data', { id: 123 });
// => "http://current-domain/api/data?id=123"
bricks.absurl(url, widget)
生成绝对 URL,基于 widget.baseURI 或 bricks.Body.baseURI。
规则
- 若 URL 已是
http://或https://,直接返回。 - 若以
/开头,则基于根路径拼接。 - 否则基于当前脚本所在目录补全。
示例
bricks.absurl('style.css'); // => "https://example.com/path/to/style.css"
bricks.path
- 类型:
string - 当前执行脚本所在的目录路径(末尾不带
/)
由 currentScriptPath() 函数设置。
bricks_resource(name)
根据 bricks.path 生成资源路径。
示例
bricks_resource('img/logo.png');
// => "https://example.com/scripts/img/logo.png"
数据处理与类型判断
isString(value)
判断是否为字符串类型。
返回值
trueiftypeof value === 'string'orvalue instanceof String
formdata2object(formdata)
将 FormData 转换为普通 JavaScript 对象。
示例
const fd = new FormData();
fd.append('name', 'Alice');
formdata2object(fd); // { name: "Alice" }
inputdata2dic(data)
提取 FormData 所有字段,对 prompt 字段进行特殊字符转义。
特性
- 自动调用
bricks.escapeSpecialChars(x)处理prompt字段 - 异常捕获:若失败则原样返回输入数据
bricks.map(data_source, mapping, need_others)
按映射规则重命名对象属性。
参数
| 参数 | 说明 |
|---|---|
| data_source | 源对象 |
| mapping | 键映射表 {旧名: 新名} |
| need_others | 是否保留未映射的原始字段 |
示例
bricks.map({ a: 1, b: 2 }, { a: 'x' }, true);
// => { x: 1, b: 2 }
bricks.delete_null_values(obj)
删除对象中所有值为 null 的属性。
示例
bricks.delete_null_values({ a: null, b: 2 }); // { b: 2 }
bricks.is_empty(obj)
判断对象是否为空(null 或 {})。
示例
bricks.is_empty(null); // true
bricks.is_empty({}); // true
bricks.is_empty({ a: 1 }); // false
颜色解析
parseRGB(colorStr)
解析 rgb(r, g, b) 格式的颜色字符串。
成功返回
{ r: 255, g: 100, b: 50 }
失败返回
null
parseRGBA(colorStr)
解析 rgba(r, g, b, a?) 格式颜色字符串,a 可选,默认 1。
示例
parseRGBA('rgba(255, 0, 0, 0.8)'); // { r: 255, g: 0, b: 0, a: 0.8 }
parseRGBA('rgb(255, 0, 0)'); // { r: 255, g: 0, b: 0, a: 1 }
异步与流式响应
streamResponseJson(response, onJson)
逐行解析 NDJSON 流式响应并回调处理每个 JSON 对象。
参数
| 参数 | 类型 | 说明 |
|---|---|---|
| response | Response | fetch 返回的响应对象 |
| onJson | Function | 每解析一行有效的 JSON 后调用该函数 |
特性
- 支持 UTF-8 解码
- 缓冲未完成的行至下次读取
- 自动忽略空行和解析错误
示例
fetch('/stream').then(res => streamResponseJson(res, json => {
console.log('Received:', json);
}));
Blob 与 Base64 转换
base64_to_url(base64, mimeType)
将 Base64 字符串转换为 Blob URL。
参数
| 参数 | 默认值 | 说明 |
|---|---|---|
| base64 | required | Base64 编码的数据 |
| mimeType | "audio/wav" |
MIME 类型 |
返回值
string:blob:URL
示例
const audioUrl = base64_to_url(base64Data);
new Audio(audioUrl).play();
blobToBase64(blob)
异步将 Blob 转换为 Data URL(包含 Base64 编码)。
返回值
Promise<string>: 如"data:audio/wav;base64,..."
示例
const dataUrl = await blobToBase64(blob);
表单与对象操作
bricks.formdata_copy(fd)
克隆 FormData 实例。
返回值
- 新的
FormData实例,内容与原实例一致。
objcopy(obj)
通过 JSON.stringify + JSON.parse 实现浅层深拷贝。
局限性
- 不支持函数、undefined、Symbol、循环引用
objget(obj, key, defval)
安全获取对象属性,类似 Python 的 .get() 方法。
示例
objget({ a: 1 }, 'b', 'default'); // "default"
bricks.obj_fmtstr(obj, fmt)
模板字符串替换,支持 ${key} 和 ${key:} 语法。
支持语法
| 语法 | 效果 |
|---|---|
${name} |
替换为 obj.name |
${name:} |
替换为 "name:value" 形式 |
${name=} |
同上(兼容旧写法) |
| 不存在的 key | 替换为空字符串 |
示例
bricks.obj_fmtstr({ name: "Tom" }, "Hello ${name}!");
// => "Hello Tom!"
调试系统
bricks.debug(...args)
统一调试输出接口。
行为逻辑
- 如果
bricks.bug === false→ 无输出 - 如果
bricks.bug === true→ 输出到控制台 + 调用栈 - 如果
bricks.bug === 'server'→ 延迟 0.1s 发送到/debug接口
示例
bricks.bug = true;
bricks.debug('Test message', { x: 1 });
// [调用位置] Test message {x: 1}
bricks.serverdebug(message)
将消息 POST 到 /debug 接口(需配合后端接收)。
内部使用
- 通过
bricks.HttpJson().post()发送 - 仅当
bricks.bug === 'server'时启用
设备检测
bricks.is_mobile()
判断是否为移动设备。
判断依据
- UserAgent 包含常见移动设备关键词
- 存在触摸事件支持(
ontouchstart,maxTouchPoints) - 屏幕尺寸 ≤ 768×1024
返回值
trueif mobile device
UI 定位与布局
archor_at(archor)
计算锚点坐标百分比。
支持锚点
| 值 | 含义 |
|---|---|
| tl | 左上 |
| tc | 顶部居中 |
| tr | 右上 |
| cl | 中左 |
| cc | 居中(默认) |
| cr | 中右 |
| bl | 左下 |
| bc | 底部居中 |
| br | 右下 |
返回值
{ x: "50%", y: "50%", left: "50%", top: "50%" }
archorize(ele, archor)
将元素定位到指定锚点,并应用 CSS transform 居中。
效果
- 设置
position: absolute - 设置
top,left - 使用
transform: translateY(-y) translateX(-x)精确居中
示例
archorize(menuEl, 'tr'); // 右上角弹出菜单
bricks.relocate_by_eventpos(event, widget)
根据鼠标点击位置智能调整组件位置,避免溢出视口。
策略
- X轴:左侧或右侧展开(避开边缘)
- Y轴:上方或下方展开
- 留出
bricks.app.charsize边距
应用场景
- 上下文菜单
- 提示框浮动定位
扩展方法(Array)
Array.prototype.insert(index, ...items)
在指定索引插入多个元素。
示例
[1, 2].insert(1, 'a', 'b'); // [1, 'a', 'b', 2]
Array.prototype.remove(item)
移除数组中第一个匹配项。
示例
[1, 2, 3].remove(2); // [1, 3]
removeArrayItems(array, itemsToRemove)
返回过滤后的数组,排除指定元素。
示例
removeArrayItems([1,2,3], [2]); // [1,3]
Cookie 操作
setCookie(name, value, days)
设置 cookie,支持过期时间。
参数
| 参数 | 说明 |
|---|---|
| name | 名称 |
| value | 值 |
| days | 过期天数(可选),null 表示会话 cookie |
getCookie(name)
获取指定名称的 cookie 值。
返回值
- 字符串或
null(未找到)
eraseCookie(name)
清除指定 cookie。
高度同步
set_max_height(w1, w2)
使两个组件的高度保持一致(取较大者)。
用途
- 并排显示的面板保持视觉对齐
调用方式
w1.set_height(h); // 假设 set_height 是组件方法
深拷贝与对象操作
bricks.extend(d, s)
递归合并源对象 s 到目标对象 d。
特性
- 仅复制自有属性
- 遇到同名对象时递归合并
- 基础类型直接覆盖
示例
bricks.extend({ a: { x: 1 } }, { a: { y: 2 }, b: 3 });
// => { a: { x: 1, y: 2 }, b: 3 }
媒体流播放
bricks.playResponseAudio(response, target)
播放 fetch 返回的音频响应。
参数
| 参数 | 类型 | 说明 |
|---|---|---|
| response | Response | HTTP 响应对象 |
| target | string | JsWidget | 组件 ID 或描述对象 |
流程
- 检查状态码是否为 200
- 转换为 Blob 并创建 Object URL
- 设置
widget.set_url(url)并调用.play()
bricks.set_stream_source(target, url, params)
流式加载音频(适用于大文件或实时流)。
使用技术
MediaSource API- 分块加载
audio/wav数据
流程
- 创建
MediaSource - 创建
SourceBuffer - 通过
fetch流式读取并appendBuffer
限制
- 需浏览器支持 MSE(Media Source Extensions)
模板渲染与组件构建
bricks.widgetBuildWithData(desc_tmpl, from_widget, data)
使用模板和数据动态创建组件。
参数
| 参数 | 说明 |
|---|---|
| desc_tmpl | 包含 ${} 占位符的 JSON 模板字符串 |
| from_widget | 父组件(可选) |
| data | 数据源对象 |
流程
- 使用
bricks.obj_fmtstr替换模板变量 JSON.parse得到组件描述- 调用
widgetBuild创建组件 - 绑定
row_data = data
可观察对象 Observable
bricks.Observable
简单的发布-订阅模型属性包装器。
构造函数
new bricks.Observable(owner, name, initialValue)
方法
| 方法 | 说明 |
|---|---|
set(v) |
设置值,若改变则触发 owner.dispatch(name, v) |
get() |
获取当前值(注意:内部应为 this.value) |
⚠️ 注意:当前代码中
get()返回的是this.v,应修正为this.value。
队列结构 Queue
bricks.Queue
标准 FIFO 队列实现。
方法
| 方法 | 说明 |
|---|---|
enqueue(e) |
入队 |
dequeue() |
出队(移除并返回首元素) |
peek() |
查看首元素(不移除) |
isEmpty() |
判断是否为空 |
size() |
获取长度 |
clear() |
清空 |
print() |
控制台输出数组内容 |
done() |
标记队列结束(自定义状态) |
is_done() |
查询是否已结束 |
示例
const q = new bricks.Queue();
q.enqueue(1);
q.enqueue(2);
console.log(q.dequeue()); // 1
DOM 创建工具
bricks.dom_create(tag, opts)
创建带有类名和 ID 的 DOM 元素。
参数
| 参数 | 说明 |
|---|---|
| tag | 标签名(如 'div') |
| opts | 选项:css(字符串)、id |
示例
bricks.dom_create('div', { css: 'menu active', id: 'main-menu' });
❌ Bug:
css.split(' ')中css应为opts.css
✅ 正确实现应为:
if (opts.css) {
const arr = opts.css.split(' ');
arr.forEach(c => e.classList.add(c));
}
bricks.element_from_html(html)
从 HTML 字符串创建 DOM 元素(仅根元素)。
示例
const el = bricks.element_from_html('<div class="box">Content</div>');
document.body.appendChild(el);
❌ 注意:
outerHTML不会修改自身标签,此方法可能无效。
✅ 推荐改用:
const div = document.createElement('div');
div.innerHTML = html;
return div.firstElementChild;
工具函数
convert2int(s)
从字符串中提取首个整数。
示例
convert2int("width: 100px"); // 100
schedule_once(f, t)
延迟执行函数(单位:秒)。
示例
schedule_once(() => console.log('After 0.5s'), 0.5);
schedule_interval(f, t)
模拟 setInterval,递归调用 setTimeout。
⚠️ 存在 bug:内部
mf.bind(func, t)使用错误,会导致上下文丢失。
建议重构为更稳定的方式。
querySelectorAllShadows(selector, el)
递归查找包括 Shadow DOM 内的所有匹配元素。
用途
- 跨 Shadow Boundary 查询组件
示例
querySelectorAllShadows('.btn', document.body);
总结
Bricks.js 提供了一套完整的前端开发辅助工具集,涵盖:
✅ DOM 操作
✅ 事件监听(Resize / Mutation)
✅ 数据转换与校验
✅ 模板引擎
✅ 异步流处理
✅ 音频播放
✅ 调试与日志
✅ 移动适配
✅ 组件通信机制
适合用于构建模块化、响应式的 Web 应用或微前端组件系统。
✅ 建议改进项
- 修复
obj_fmtstr和Observable.get()中的变量名错误- 优化
schedule_interval的递归绑定问题- 替换
element_from_html的实现方式- 文档补充各组件依赖关系图
📄 文档版本:v1.0
📅 最后更新:2025年4月5日