headless ui 是一种新的交互逻辑开发理念,表示仅提供 UI 元素和交互的逻辑、状态、处理和API,但不提供标记、样式或预构建实现(或另外实现)。
构建复杂 UI 最难的部分通常围绕状态,事件,副作用,数据的计算和管理。通过将标记,样式和实现细节先剔除,我们的逻辑和组件可以更模块化和重复使用。
优势
无UI
这似乎有违直觉,一般情况下我们都会去尝试使用自带设计体系的组件库。但如果某天,我们的设计师/产品,突然拿出一套炫酷的设计/需求时,作为前端的我们大概率是崩溃的。
在既有的体系上修改,往往比从零开始设计会花费更多时间,且需要解决更多兼容问题,所以在需要定制设计体系,或频繁更换设计主题的场景,无 UI 的组件库反而是有利的。再加上现如今样式管理方案的发展,定制样式或设计体系可以完全独立进行,使用 tailwindcss 这样的平台协助解决。
跨平台
前端目前的渲染框架大致有 react、vue 等,headless 组件库提供的功能核心只面向组件内部的自有逻辑及状态,具体的渲染,事件绑定等,属于渲染框架层面的内容,组件库则通过一个适配层(adapter)来实现,所以核心部分复用,单独开发适配层,则能够实现跨平台,甚至小程序、跨端等其他开发场景也可用类似的设计来处理。
功能预置/定制
功能预置与传统组件库所要实现的目的是相同的,但由于传统组件库必然控制标签渲染,预置功能必然影响后续定制,而 headless ui 的功能预置可以仅处理核心的数据层面的内容,预置功能的同时,对定制(数据的定制,渲染的定制)可以完全开放。
功能定制指提供某种机制,或通过某种方式(如 react 中的 props),让外部对已有实现进行额外定制及功能添加,由于核心部分可以先不处理渲染部分,不受框架约束,只需要处理内部状态,管理配置即可,所以定制功能的添加,几乎无限制,自由度很高。
简单来讲,headless ui 的结构在提供功能预置的同时,保留了定制的灵活度,为未来的拓展留下了余地。
劣势
使用繁琐
由于 headless 核心只提供内部状态逻辑,实际渲染标签的结构,如何嵌套,定制内容的注入,都是需要外部进行的,当然像上面提到的 adapter 如果实现较重,则可解决该问题,这样实际使用时的体感与传统组件库是相同的,如果需要更加复杂的定制时,自行实现一个新的 adapter 即可。
开发复杂度
由于需要将核心脱离出页面结构,此处对功能拆分,抽象管理需要更高的要求,对开发者的心智负担是比较重的。另外由于同时脱离了渲染框架,像一些通常由框架提供的 memo、context 等功能,需自行实现并管理。
已有实现
目前依照 headless ui 思想的实现有以下内容,后续会对部分内部实现进行具体分析:
Semi Design
bytedance.feishu.cn/wiki/wikcnO…
TanStark Table
Headless UI
headless ui 的核心内容都是逻辑、状态、数据,也就是纯 js,这部分内容的兼容性不成问题,所有“脏”东西的部分都留给了 adapter,此处会调用 核心 的内容,创建逻辑实例,注入状态到具体标签,以及标签嵌套,事件监听等内容。
了解了 headless ui 的思想后,可以意识到一个功能全面可定制的 headless 组件库,它的生命周期可能会很长(至少核心部分如此),无论以后的渲染框架怎么变,平台怎么变,核心功能是会(实现正确的情况下)被长久保留的,投入高的同时产出也随时间增高。目前没有太多的具体实现,最佳实践也可能暂未出现,但这个方向应该是对的,值得尝试。
也许我们不需要 react 也能写好组件逻辑,也许我们不需要 hooks 来实现逻辑封装,我们可以先用纯 js 整理逻辑提供接口,再去管标签样式事件......
这一切感觉都挺陌生和有趣的,后续会有更多内容及实现,快慢不定(希望不会弃坑),由于本人水平有限,此系列内容为个人的总结及理解,欢迎各位的指正,一起学习讨论。