
写代码的人都有一种朴素的惰性优先复用现成的避免重复造轮子。当初图扑软件计划从零搭建专属 Web UI 组件库内部最先提出质疑的正是我们团队自己。本文会讲清这支“画布之笔”为何必须自研再附上极简示例代码带你上手实操。01 先把你的白眼接住我猜你看到“又一套 UI 组件库”这几个字心里已经泛起抵触。「市面上前端组件库难道还不够多按钮、输入框、表格、下拉框开源方案随处可见随便挑一个成熟方案不香吗图扑何必重新开发」我们十分理解这份疑问其实立项之初我们内部也有同样的顾虑。如果现有组件能满足需求没人愿意从头打磨文本录入这块硬骨头。光标闪烁、文本选中、中文输入法候选框任意一处细节都足够耗费大量开发精力。剧透一下这类复杂底层能力 HT UI 并未全部自研后文会讲到框架如何巧妙兼容原生能力。但痛点恰恰藏在大家总想复用现成方案、避免从零开发的固有思路里。市面上绝大多数 Web UI 库本质上都是在 DOM 这套基础架构上叠加封装。单个按钮对应一个button标签一张表格由上千个td组成一棵树形组件是层层嵌套的div。这类库在常规表单后台中表现流畅可如果你的项目并非简单管理系统而是重型工具软件、低代码可视化搭建平台、在线 IDE、十万行级别的大型表格与树形结构、属性面板密集的专业编辑器这类产品界面上同时存在数百上千个控件时DOM这套架构就会彻底承压过载。02 重场景里DOM 是怎么累垮的深耕这类项目的开发者大概率都踩过这些坑低代码搭建编辑器场景左侧组件树、中间画布主体、右侧整列属性面板数百个控件同屏渲染。传统 DOM 方案中每个控件都对应一组嵌套标签浏览器仅维护这些节点的位置、样式、层级关系就会占用大量 CPU 资源极易出现设备风扇高速运转、页面卡顿的情况。组件密集型工具软件场景工具栏、多页签、可拖拽面板、可拉伸分割条层层叠加。用户切换页签、拖拽面板、拉伸分割条的每一次操作都会触发大范围的 DOM 回流reflow与重绘repaint操作拖拽延迟、画面卡顿掉帧交互体验极差。十万行级树表格场景仅将海量 节点插入 DOM就足以让浏览器严重卡顿更无法保障流畅的滚动、展开、折叠交互效果。这些场景的共性十分鲜明元素数量多、状态变化频繁、且要求交互极致流畅。DOM 天生适配“结构稳定、节点数量可控”的文档类页面。强行用它承载控件密集、交互频繁的重型界面就好比让擅长写楷书的老先生去刷大面积墙面——不是能力不足而是工具用错了场景。图扑深耕专业工具软件研发多年最常遇到的就是这种“控件密集、交互高频”的复杂界面场景。被实际业务场景倒逼之后我们得出了一个简单直接的结论既然 DOM 堆叠的方式扛不住那就直接改用 Canvas 绘制。03 所谓“纯 Canvas”到底纯在哪我们以一个普通按钮为例拆解两种实现方案的差异。传统 DOM 实现的按钮结构十分繁琐一层button外层标签、多层span嵌套承载文字、大量CSS控制样式、搭配伪元素实现图标效果……仅仅一个按钮就需要浏览器维护一整棵小型 DOM 子树。一千个按钮就是一千棵独立的DOM子树。而 HT UI 的实现逻辑完全不同组件的所有视觉样式——边框、背景、文字、图标、选中态、禁用态全部通过 Canvas 画笔实时绘制生成。打开Chrome开发者工具的Elements面板查看HT UI按钮看不到繁杂的嵌套标签只有极简清晰的几层节点View一个组件最外层容器负责页面占位与交互事件接收通过button.getView()即可获取该节点RootCanvas一块 组件所有可视化内容包括边框、背景、文字、图标全部绘制于此ContentDiv / ScrollBar / DisabledDiv分别为内容容器、滚动条、禁用遮罩按需渲染、不冗余占位。一句话定义这份“纯粹”仅保留极简 DOM 壳子负责交互事件所有视觉渲染工作全部交由 Canvas 承载。这套方案直接将页面DOM节点数量缩减一个量级大幅减轻浏览器渲染负担。这并非炫技而是复杂密集界面场景倒逼出的最优解决方案。这里必须坦诚划定技术边界还记得开篇提到的剧透吗唯一的例外是文本录入类组件。输入框、文本域等需要手动录入内容的组件会嵌套原生input / textarea标签专门承接光标渲染、文本选区、中文输入法交互等能力。这类组件的边框、背景、文字展示等视觉样式依旧由Canvas绘制真正承接键盘输入交互的是原生 DOM 元素。为何不全程纯 Canvas 实现因为输入法IME是操作系统级的底层能力强行用Canvas模拟光标、输入法候选框不仅开发成本极高、兼容性差还无法达到原生交互体验得不偿失。懂得适时取舍、精准妥协也是技术研发的一种修养。除文本录入场景外HT UI 所有组件的视觉效果均由 Canvas 纯手绘实现。基于 HT UI 搭建的数据中台操作界面大量表格、图表、控件同屏纯Canvas绘制下依旧顺滑。这里顺便分享一个实用调试技巧所有DOM节点均挂载ht属性用于标识身份例如按钮View节点会标注ht-viewht.ui.Button。若遇到界面异常如按钮不显示、样式错乱可通过两步快速定位问题先检查DOM壳子是否存在存在则说明布局正常问题出在绘制逻辑不存在则是DOM 布局层级出现异常无需盲目排查海量标签。04 性能这件事打个不一样的比方只说“性能更快”太过笼统等于是在耍流氓。下面我们用通俗的类比让大家直观理解性能差异的核心原理。想象一块白板上面要呈现一千个图形。DOM 方案如同往白板上粘贴独立磁贴。每个图形都是一块独立磁贴可单独拖拽、叠放、改样式灵活性高但弊端极其明显白板需要逐个记录每一块磁贴的位置、层级、边界信息。磁贴数量越多白板的承载压力越大挪动单块磁贴还可能引发周边大面积磁贴错位、重排。纯 Canvas 方案则是直接用画笔在白板上绘制图案。一千个图形终究只是白板上的一片笔迹需要修改局部内容时仅擦除对应区域、局部重绘即可。无论绘制十个还是一千个图形白板始终是唯一的载体无需逐个记录元素信息仅需管控“当前帧需要刷新的区域”。落地到实际开发中HT UI 重绘时仅会刷新产生变化的“脏区域”通过一次requestAnimationFrame完成所有绘制更新无需遍历、处理成千上万个DOM节点。节点数量恒定、绘制刷新范围可控这就是 HT UI 在重场景下依旧稳帧流畅的底气。当然客观来说无需神化这套能力如果只是开发仅有几张表单的常规后台管理系统HT UI 的高性能优势完全无法发挥实属大材小用。但只要你的界面存在“元素密集、状态多变、交互频繁”的特点这套Canvas绘制架构的优势就会彻底凸显。05 上手体验极简代码快速落地理论铺垫再多不如实战验证。下面用最简示例直观感受 HT UI 的上手门槛。首先引入两个文件scriptsrcht.js/scriptscriptsrcht-ui.js/script随后仅需 5 行代码即可实现一个可点击的功能按钮// 创建按钮实例varbuttonnewht.ui.Button();button.setText(Hello World);// 绑定点击监听事件button.on(click,function(e){alert(Hello World);});// 挂载至页面左上角定位宽高自适应内容button.addToDOM(window,{x:10,y:10,width:wrap_content,height:wrap_content});注意代码中的wrap_content机制熟悉Android开发的开发者会十分熟悉即“包裹内容自适应尺寸”按钮宽高由内部文字、内容自动适配。HT UI 刻意沿用业界成熟的命名规范与设计范式降低学习成本首次使用也能凭直觉上手。06 两块基石Border 与 Drawable想要自定义按钮样式、实现个性化皮肤需要先了解 HT UI 的两大核心基础能力Border边框与Drawable可绘制对象。前者统一管控组件边框样式后者负责实现组件背景、图标等视觉内容。二者均为接口内置丰富的默认实现无法满足需求时可直接继承拓展、自定义绘制逻辑。先看背景样式配置。仅 1 行代码即可将按钮背景设置为圆角纯色样式// ColorDrawable纯色背景 自定义圆角半径button.setBackground(newht.ui.drawable.ColorDrawable(#1ABC9C,6));Drawable体系支持丰富的绘制能力。其中ImageDrawable专门用于图片渲染内置fill、uniform、centerUniform、center、cover五种图片拉伸模式默认centerUniform一键即可实现图片铺满、等比缩放、居中展示等常见效果。除此之外NinePatchImageDrawable九宫格拉伸更是适配各类异形组件的利器。移动端开发者对此并不陌生通过九宫格机制可实现图片四角固定不变、中间区域自由拉伸的效果气泡弹窗、按钮背景、圆角面板等组件靠一张素材图即可适配所有尺寸极大精简资源文件。HT UI 的九宫格格式与Android原生规范基本一致支持通过官方draw9patch.jar工具快速制作适配素材。// 九宫格背景四角固定不变中段任意拉伸无模糊失真view.setBackgroundDrawable(newht.ui.drawable.NinePatchImageDrawable(test.9.));边框能力同样具备高度开放性。内置边框样式可满足绝大多数常规场景若需要实现异形、个性化边框只需继承ht.ui.border.Border重写getLeft/getRight/getTop/getBottom方法定义边框宽度并重写drawBorder方法即可自主绘制。绘制前需通过g.beginPath()开启独立路径既能保障绘制性能又能避免样式串色这也是Canvas绘制的基础规范。这种“内置能力全覆盖、拓展接口全开放、支持全权接管绘制逻辑”的设计正是后续文章要拆解的“组件丰富度”与“样式百变适配能力”的核心根基。一支笔好不好不只看它自带多少颜料更看你想调配独特色调时它会不会把你束缚。07 这一篇请记住三句话HT UI 并非传统的 DOM 组件库它将所有视觉渲染能力交由 Canvas 实现。极简DOM壳子承接交互事件Canvas画笔全权负责视觉呈现。它为高密度、高复杂度界面场景而生。重型工具软件、可视化搭建平台、大数据表格与树形结构、多控件密集编辑器控件越多、交互越密集性能优势越突出。它极致降低开发与上手成本。五行Hello World贴近直觉的命名规范、开放完备的拓展接口性能强劲却极易上手。下一篇我们将聚焦”量”与”序”HT UI 究竟提供了多少组件底层那套万物归一的DataModel——为什么在HT的体系里一个按钮和一万个节点本质上是同一种存在。……