出处:掘金
原作者:易师傅
前言
近日,百无聊赖,上网游逛,在《2023 JavaScript Rising Stars》上看到了一个令人匪夷所思的仓库 shadcn/ui,就一年那个 star 数啊,蹭蹭的上涨了 39500 颗星星
看了源代码,原来是一个基于 Headless UI 组件库 radix-ui 的上层 React UI 组件库,心想 Headless UI 组件不是几年前才火起来的玩意嘛,怎么在前端怎么就有一席之地了呢?
看样子真是一代新人换旧人,一代技术一代新人,技术的日新月异也未免是个坏事~
Headless 的历史和背景
我相信很多同学对计算机界的 Headless 比较熟悉,因为 Headless 一词最初就是来源于 Headless Computer(无头计算机)也就是 Headless System(无头系统),维基百科的介绍为:
无头系统(Headless System)是指已配置为无须显示器(即“头”)、键盘和鼠标操作的计算机系统或设备。无头系统通常通过网络连接控制,但也有部分无头系统的设备需要通过 RS-232 串行连接进行设备的管理。服务器通常采用无头模式以降低运作成本。
后来慢慢的就有了 Headless Browser(无头浏览器)、Headless CMS、Headless BI 等常见的 Headless 系列
Headless UI
在 2017 年,一个在基于 React 的高阶函数(HOC) 以及复合组件(Compound Components) 研发的 downshift 诞生了,它的诞生无疑间接的促使了 Headless UI 的来临
在 2018 年 6 月 22 日,一篇受到 downshift 启发介绍 Headless User Interface Components 的文章应运而生,只是那时候的评判大多褒贬不一,有赞同博主的,也有质疑博主的;由此 Headless UI 一词正式被大家所认知
后来在 2018 年 10 月 26 日,改变现有 React 和 Vue 格局的《React Conf 2018》大会引入了现有屌爆了的 React Hooks 概念之后,Headless UI 概念才慢慢的被大家所接受
因为在大家后知后觉中,其实发现 Headless UI 概念其实与 React Hooks 概念大同小异,只是差别在于一个更多的实现所有数据或交互的状态逻辑层,一个实现现有常见的 UI 库的数据或状态逻辑层(下面会详细介绍)
但是那时国内其实对 Headless UI 这一概念认知还较少,在国内大家更多关心的还是 React Hooks
就这样到了 2020 年,在国内社区有较高知名度和影响的 Tailwind Labs 团队介绍的 Introducing Headless UI 中慢慢开始在国内社区崭露头角
什么是 Headless UI
Headless UI 是一种前端开发的方法论(亦或者是一种设计模式),其核心思想是将用户界面(UI)的逻辑和交互行为与视觉表现分离开来
换句话说,Headless UI 提供了一种方式来构建只包含逻辑和功能的用户界面组件,而不依赖于特定的 CSS 样式框架或 UI 库
具体而言,Headless UI 的组件通常是纯粹的 JavaScript(或其他编程语言)组件,它们包含了一些交互逻辑和状态管理,但没有任何与视觉样式相关的代码
为什么需要 Headless UI
众所周知,在传统的 UI 组件中,通常被拆分为两大部分:
- 外观样式(传统组件 UI 展示层)
- 逻辑部分(Headless UI 部分)
外观样式负责展示元素标签与样式,而逻辑组件部分则负责处理数据逻辑、状态管理和用户交互等功能
传统 UI 组件框架
传统 UI 组件包含:
- HTML 标签
- CSS 样式
- 用户交互
- 数据逻辑
- 状态管理
我相信在座的各位同学,都有用过现成的一些 UI 组件库,例如:Bootstrap
、Material UI
、Ant Design
、element-ui
等,在其中,我们能看的出来,传统 UI 组件的优势主要有:
- 开箱即用:字面意思,直接安装后就可以用了
- 易学易用:文档嘛,一看就懂,一用就废
- 功能性全:根据这么些年的发展,这些个开源组件库,几乎能遇到的 bug 都给整治了
- 部分响应式:这不 Bootstrap 就是一个很好的例子吗
那么用过的同学肯定也知道现成 UI 组件库的一些痛点,比如:
- 样式难以定制:正所谓一个萝卜一个坑,一个公司一套样式,一个项目一套样式,那么这时候的劣势就无限被放大了
- 耦合性高:传统 UI 组件库通常将界面样式、数据逻辑和用户交互等功能耦合在一起,导致代码难以维护和扩展
- 创意受限:公司设计师根据现有传统 UI 组件库提供的一套固定组件和样式,他们想要拓展创意,都受到了很大的影响
- 依赖过多:一些传统 UI 组件库可能依赖于大量的第三方库和插件,增加了项目的复杂性和维护成本
研发中实际场景的重现
1. 需求第一期
参与人员:前端 A、后端 A、设计师 A、产品 A
其中有一个功能要实现一个日期选择组件,下图是第一期的实现
你噼里啪啦一顿操作的实现了
那么现在需求迭代了
2. 需求第二期
参与人员:前端 A、后端 A、设计师 B、产品 B
这时候问题就来了,设计师 B 想把这个日期选择的样式改一下,改成如下:
那么此时阁下又该如何去面对呢?
- 魔改?
:deep
强制改?!important
强制改?- 重写自定义?
- 和设计师沟通?
- 沟通不过来打一顿?
- 不解气,这破工谁爱打谁打
那么我们此时不妨换一种思路,试试用 Headless UI 解决看看
Headless UI 的解决方案
普通的 Headless UI 组件包含:
- 数据逻辑
- 状态逻辑
- 用户交互
其实 Headless UI 的一些拓展还可以包括浏览器兼容性、无障碍访问等功能
用传统 UI 组件库实现一个 Date
组件代码:
<template>
<!-- ... -->
</template>
<script>
// ...
</script>
<style>
// ...
</style>
能看到组件的逻辑与标签和样式都是高度耦合在一起的,很不利于拓展
再看下 Headless UI 实现的组件,截取部分:
能看到 Headless UI 实现的组件简便了很多,完全没有所谓的样式集成在里面了,你想怎么改就怎么改
说白了,就是 Headless UI 的出现就是为了解决传统 UI 组件框架的缺点,你不是要定制样式吗,现在我 ™ 连样式都不给你,全部由你自己来实现,爱咋滴咋滴,想怎么折腾就怎么折腾,无论多离谱的定制化都能实现
Headless UI 的优势和特点
- 灵活性高:因为 Headless UI 将组件的逻辑和样式分离,咱们可以根据项目的需要,想怎么玩就怎么玩
- 可定制:样式都没了,我这不是想咋定制就定制了吗,你别说两个设计师,100 个都不成问题,还担心啥呢?
- 轻量级:只有逻辑了,那可不少了一大堆代码了
- 测试友好:写过单元测试的同学应该都知道,有样式组件和没样式组件的单元测试那就是一个天一个地
- 无需学习新的样式框架:我只看你的 API 不就行了,那样式有啥好关注的
Headless UI 的应用场景
根据个人实际经验,我总结出来的一些实际应用场景:
- 跨平台应用:如果你司同个项目在多个平台上共存,那么此时的样式肯定都是不大一致的,那么现在 Headless UI 就可以发挥它的作用了
- 定制化界面:如果你们项目需要高度定制样式和功能,我觉得这是一个很不错的选择
- 公司项目较多:因为一个项目会存在很多个不同样式同逻辑的组件,所以在一个公司中,业务场景较大,以及项目较多,不失为一个很好的选择
当然 Headless UI 也有缺点,并不适用于所有的项目:
- 如果你项目使用简单,对设计没有较大的要求,还是用现成的 UI 库比较合适,毕竟开箱即用
- 如果公司大家的技术水平参差不齐,还是别瞎整了,还是用现成得吧
- 切莫为了跟风瞎折腾技术,从实际出发