开场白
大家好,我是 Lim。
前段时间看到一个新概念:Headless UI,什么是 Headless UI?为什么需要 Headless UI,今天我们来了解一下。
什么是 Headless UI?
想象一个组件 Checkbox,它是这样一个组件,默认展示的是一个方块,点击后会打勾,再次点击后会取消勾选;抽象来看由三部分构成:State、Logic 和 View, 是否勾选是 State,点击勾选是 Logic,可视的部分(方块和对勾)是 View。
这里给出一句话定义 Headless UI:没有 View 的 UI。
诶?等等,没有 View 还叫 UI 吗?这样命名的原因是,剩下的两部分 State + Logic 是为 View 服务的,而且需要与 View 配套使用,所以命名成 UI 也无伤大雅。
剥离 View 留下 State + Logic,这不是 Hooks 解决的问题吗?没错,Headless UI 与 Hooks 非常契合,顺便说一句,在 Hooks 出现之前,分离关注点技术还有 renderProps 和 HOC,下面会介绍基于 Hooks 和 renderProps 实现 Headless UI 的产品。
为什么需要 Headless UI?
讲个故事。平台 A 是基于 ArcoDesign 搭建的,UI 同学要求 InputNumber 的调节按钮是红色的,可是 InputNumber 没有暴露修改调节按钮样式的属性;
魔改样式是前端同学的常规操作,只要找到调节按钮的类名就可以覆盖样式了,问题解决;
不久后 UI 同学提出 InputNumber 的两个调节按钮要改成 Button,并且都放在底部,就像这样:
前端同学很为难,组件库并不支持,魔改也无从下手,算了,手写一个吧。
如果有 Headless UI 呢? 问题似乎就简单了,可以这样解决,直接看代码:
这不是 alibaba/hooks 提供的 useAntdTable 吗?其实不一样,useAntdTable 返回的 tableProps 可以看成 State,并不包括 Logic。
Headless UI VS 普通组件
普通组件是指常用组件库提供的组件
-
Headless UI支持样式完全自定义,普通组件仅支持小改动;
-
Headless UI 使用成本高,需要自定义样式;普通组件开箱即用;
Tailwind Headless UI(renderProps)
基于 renderProps 实现,通过 renderProps 暴露 State 和 Logic,然后用户基于 State 和 Logic 自定义样式。然而 hooks 出现的动机之一就是解决 renderProps 嵌套地狱, 所以 tailwind 未来应该也会基于 hooks 去重新实现。
ReactTable(Hooks)
基于 Hooks 实现,Hooks 的返回值就是 State 和 Logic。
看一下 useReactTable 返回的内容:
Headless UI 相关产品
-
Headless UI 库
-
单组件
总结
Headless UI 是内核,基于内核衍生于各种各样的组件库,可能是组件库演化的重要路径。
不过 Headless UI 是个全新的理念,必然会经历群魔乱舞的阶段,此时会出现各种各样的 Headless UI 库,最终再收敛成一个框架无关的标准,值得实践和期待。