Headless 组件即无 UI 组件,框架仅提供逻辑,UI 交给业务实现。这样带来的好处是业务有极大的 UI 自定义空间,而对框架来说,只考虑逻辑可以让自己更轻松的覆盖更多场景,满足更多开发者不同的诉求。
我们以 headlessui-tabs 为例看看它的用法,并读一读 源码。
概述
headless tabs 最简单的用法如下:
import { Tab } from "@headlessui/react";
function MyTabs() {
return (
<Tab.Group>
<Tab.List>
<Tab>Tab 1</Tab>
<Tab>Tab 2</Tab>
<Tab>Tab 3</Tab>
</Tab.List>
<Tab.Panels>
<Tab.Panel>Content 1</Tab.Panel>
<Tab.Panel>Content 2</Tab.Panel>
<Tab.Panel>Content 3</Tab.Panel>
</Tab.Panels>
</Tab.Group>
);
}
以上代码没有做任何逻辑定制,只用 Tab
及其提供的标签把 tabs 的结构描述出来,此时框架能提供最基础的 tabs 切换特性,即按照顺序,点击 Tab
时切换内容到对应的 Tab.Panel
。
此时没有任何额外的 UI 样式,甚至连 Tab
选中态都没有,如果需要进一步定制,需要用框架提供的 RenderProps 能力拿到状态后做业务层的定制,比如选中态:
<Tab as={Fragment}>
{({ selected }) => (
<button
className={selected ? "bg-blue-500 text-white" : "bg-white text-black"}
>
Tab 1
</button>
)}
</Tab>
要实现选中态就要自定义 UI,如果使用 RenderProps 拓展,那么 Tab
就不应该提供任何 UI,所以 as={Fragment}
就表示该节点作为一个逻辑节点而非 UI 节点(不产生 dom 节点)。
类似的,框架将 tabs 组件拆分为 Tab 标题区域 Tab
与 T