Headless UI 组件库的终极解决方案

4,450 阅读3分钟

image

开场白

大家好,我是 Lim。

前段时间看到一个新概念:Headless UI,什么是 Headless UI?为什么需要 Headless UI,今天我们来了解一下。

什么是 Headless UI?

想象一个组件 Checkbox,它是这样一个组件,默认展示的是一个方块,点击后会打勾,再次点击后会取消勾选;抽象来看由三部分构成:StateLogicView, 是否勾选是 State,点击勾选是 Logic,可视的部分(方块和对勾)是 View。

这里给出一句话定义 Headless UI:没有 View 的 UI。

诶?等等,没有 View 还叫 UI 吗?这样命名的原因是,剩下的两部分 State + Logic 是为 View 服务的,而且需要与 View 配套使用,所以命名成 UI 也无伤大雅。

剥离 View 留下 State + Logic,这不是 Hooks 解决的问题吗?没错,Headless UIHooks 非常契合,顺便说一句,在 Hooks 出现之前,分离关注点技术还有 renderPropsHOC,下面会介绍基于 HooksrenderProps 实现 Headless UI 的产品。

为什么需要 Headless UI?

讲个故事。平台 A 是基于 ArcoDesign 搭建的,UI 同学要求 InputNumber 的调节按钮是红色的,可是 InputNumber 没有暴露修改调节按钮样式的属性;

image

魔改样式是前端同学的常规操作,只要找到调节按钮的类名就可以覆盖样式了,问题解决;

image

不久后 UI 同学提出 InputNumber 的两个调节按钮要改成 Button,并且都放在底部,就像这样:

image

前端同学很为难,组件库并不支持,魔改也无从下手,算了,手写一个吧。

image

如果有 Headless UI 呢? 问题似乎就简单了,可以这样解决,直接看代码:

image

这不是 alibaba/hooks 提供的 useAntdTable 吗?其实不一样,useAntdTable 返回的 tableProps 可以看成 State,并不包括 Logic

image

Headless UI VS 普通组件

普通组件是指常用组件库提供的组件

  1. Headless UI支持样式完全自定义,普通组件仅支持小改动;

  2. Headless UI 使用成本高,需要自定义样式;普通组件开箱即用;

Tailwind Headless UI(renderProps)

基于 renderProps 实现,通过 renderProps 暴露 StateLogic,然后用户基于 StateLogic 自定义样式。然而 hooks 出现的动机之一就是解决 renderProps 嵌套地狱, 所以 tailwind 未来应该也会基于 hooks 去重新实现。

image

ReactTable(Hooks)

基于 Hooks 实现,Hooks 的返回值就是 StateLogic

image

看一下 useReactTable 返回的内容:

image

Headless UI 相关产品

  • Headless UI 库

  • 单组件

总结

image

Headless UI 是内核,基于内核衍生于各种各样的组件库,可能是组件库演化的重要路径。

不过 Headless UI 是个全新的理念,必然会经历群魔乱舞的阶段,此时会出现各种各样的 Headless UI 库,最终再收敛成一个框架无关的标准,值得实践和期待。

参考