Skip to content

Headless UI 和 React Hooks

在 React 中,基于类组件存在如下缺点

  1. 内部状态难以复用
  2. 代码较为复杂以及散乱的生命周期函数

而 React Hooks 赋予了在函数组件中,管理状态,管理副作用(可以近似模拟生命周期)的同时,也推动了组件的拆分及复用。在 React Hooks 基础上,Headless UI 应运而生。

Headless UI

业务逻辑

Headless UI 顾名思义,就是没有 UI 的组件,即组件只提供业务逻辑,UI 则由开发者自己提供。

什么是业务逻辑?业务逻辑,指的此次开发功能的目的和达成目的的步骤,例如我想开发一个简易计算器,那么计算器的业务逻辑就是

  1. 得到一个数字(用户输入)
  2. 得到一个运算符(用户输入)
  3. 得到一个数字(用户输入)
  4. 输出结果

我只要能够实现上述业务逻辑,那么无论这些按钮是长还是圆,颜色是绿还是红,在 Input 输入还是在 Textarea 输入,都是属于 UI 范畴了,在业务逻辑层面是无需关心的

那么,我提供如下的接口即可满足计算器的业务逻辑

UI

const { inputPrefix, inputSymbol, inputAfter, getResult } = useCalculator();

什么是 UI?UI(User Interface) 指的是用户界面,即用户看到的界面,例如上述的计算器,我需要提供如下的 UI 组件

  1. 一个输入框
  2. 一些运算符按钮(+,-,*,/)
  3. 一个输入框
  4. 一个计算结果按钮
  5. 一个显示结果的地方

我提供通用的业务逻辑接口,而具体的 UI 组件,则由开发者自己提供,例如如下的 UI 组件

// 这是业务逻辑
const { inputPrefix, inputSymbol, inputAfter, getResult } = useCalculator();
// 这是UI
const
<p>{result}<p>
<Input onChange={inputPrefix}>
<SymbolsGroups onClick={inputSymbol}>
<Input onChange={inputAfter}>
<Button onClick={() => result = getResult()}>

据此我已实现了计算器的所有功能了,在实现功能的同时还具有如下特点

  1. 复用性,高度抽象的业务逻辑,原则上来说可以在任何地方复用(在跨语言或框架有所区别,但是思路相同)
  2. 扩展性,举个例子,我现在想增加一个【清空】按钮,那么我只需要在业务逻辑中增加一个清空按钮的逻辑,然后在 UI 中增加一个清空按钮的 UI 组件即可,无需修改以前的逻辑
  3. 可测试性,因为业务逻辑是高度抽象的,所以可以很方便的进行测试,而 UI 组件则需要开发者自己提供测试代码,当然 UI 测试不太容易编写
  4. 效率和成本 a. 需要剥离业务和 UI,而我理解前端本身就是偏向 UI 的,所以需要更高的抽象思想,开发者要求会更高 b. 需要开发者自己提供 UI 组件,成本还挺高,没有用组件库快

今年最火的 chakra-ui 组件库就是这么设计的

  1. 底层,提供 Headless UI,可完全自己定制 UI
  2. 上层,提供完整的 UI 组件,可以直接使用

Headless 的思考

业务的本身是为了产生收益,而产生收益的是产品售卖,信息售卖,服务等等,从极端点角度来说,UI 并不能创建收益,UI 仅仅是为了引导用户来创建收益,用户无需通过 UI,通过指令也是一样可以创建收益

所以说 UI 是业务后续的表现形式,将业务逻辑和 UI 拆分开是最为合适的。业务逻辑较为纯粹,是可以测试的,无论后续怎么改,只要测试能跑通就不会出大问题

关于业务逻辑和复用这件事,其实可以参考后端,在后端只有一套数据模型,同时可以一套接口来接入 PC 端,小程序端等等,没有说针对 PC 端搞一套数据模型和业务逻辑,针对小程序又是另一套