shadcn/ui 是 2023 年在 GitHub 上星星数量增长最多的项目,总共获得了 39.5k 的 star,而且在 2023 年 1 月的时候才在 GitHub 发布,接着 2024 年 3 月已经增长到 50K star,这个增长速度非常可怕,究竟它是靠什么让大家都愿意贡献给它一颗 star 呢?
目前一些热门的 UI 库,包括 MUI、Ant Design 和 Chakra 等等,然后就找到了这个 2023 年最热门的项目。刚开始看 Shadcn UI 组件的样式时并没有觉得令人惊艳,组件也跟其他 UI 库没什么不同,那为什么它会是 2023 年 star 增长数量最多的项目呢?
在这篇文章中会详细介绍 Shadcn UI,并且会整理一些在选择 Shadcn UI 大家会遇到的问题,提供给大家做技术选型的参考。
首先明确:Shadcn UI 不是 组件库
Shadcn UI 与常见的 MUI、Ant Design 和 Chakra 等等的组件库不一样,它并不是一个组件库,那它是什么呢?
实际上它是汇集了各种组件的一个项目,你可以选择需要的组件,然后复制粘贴到你的项目中。而且它没有 npm 包,这意味着你不会在 package.json 中看到 Shadcn UI。
看到它的使用方式,你可能会疑惑,这个和其他的组件库没有什么不同啊?
Radix UI 是一个 headless 组件库,这表示它的组件没有任何的样式,它提供了可以定制化样式的方式,让我们自定义组件的样式。
此外,Radix UI 的所有组件都符合 WAI-ARIA 的要求,如果你需要建立具有可访问性的项目,Radix UI 无疑是一个好的选择。 另外一点,是 Radix UI 的所有组件都可以单独下载,你不用在一开始就安装整包的组件库,而是安装需要的组件到你的项目中即可:
npm install @radix-ui/react-dialognpm install @radix-ui/react-dropdown-menunpm install @radix-ui/react-tooltip
如果你不需要 Shadcn UI 提供的样式,也可以自己使用 Radix UI 封装成所需的组件库。
Tailwind CSS 无疑是近年来大家最常听到实现了原子化 CSS 的 CSS 框架,而 Shadcn UI 则是用了 Tailwind CSS 封装了 Radix UI 的组件,你从 Shadcn UI 上复制的组件都有 Tailwind CSS 的踪迹。
除了 Tailwind CSS 之外,另一个值得一提的是 class-variance-authority(cva)这个库,这个库也会在 Shadcn UI 中经常看到,它让组件有了 variant 的功能。
Shadcn UI 的主要功能就是让你复制组件的源代码,它提供了 CLI 跟手动复制两种方式,使用 CLI 便可以很快速地将组件新增到你的项目中:
npx shadcn-ui@latest add button
问题1:将 Shadcn UI 的组件源码下载下来,那不得需要自己维护吗?
在看到这个项目的时候,很多人都会有这个问题,如果遇到 bug 的时候怎么办?这的问题不太准确,有两点是大家需要思考的。
首先,不论是 Shadcn UI、MUI 或 Ant Design,只要修改了其组件的样式都需要我们自己维护,所以维护这个问题是必然的,除非你不需要定制样式。
其二,Shadcn UI 的底层是 Radix UI,组件的功能是实现在 Radix 上面,跟 Shadcn UI 没有关系,所以当发生了 bug 或是需要新功能时,则是要去看 Radix UI 是否有更新,而不是 Shadcn UI。
所以这个问题的答案是“对的,你要自己维护,但是只需要维护样式的部分”。
问题2:Shadcn UI 的项目 issue 很多怎么办?
Shadcn 作者在加入 Vercel 之后更新频率变低了,所以 issue 现在蛮多的,而且更新速度并不一定会如大家预期。
但如上个问题所述,Shadcn UI 里面只有样式,组件的功能是 Radix UI 提供的,所以当发生问题时要看的是 Radix UI 的状况,而并非 Shadcn UI。除非你需要的是 Shadcn UI 的 issue 提到的某个新的功能或是样式,但届时也许也是用复制粘贴的方式去更新 codebase 中的组件。
什么时候不要使用 Shadcn UI?
我想这个是大家都想问的一个问题,可以快速总结为几点:
因为 Radix UI 的组件都没有样式,这意味着所有的组件样式都得自己建构跟维护,这是个双刃剑,你拥有组件样式完整的控制权,但就得花费更多心力去维护。如果你依赖了 Ant Design,而按钮只改了 border-radius,其他样式则是由 Antd 提供,不用花费很多心力去维护样式,只需要担心升级的时候会不会跑版,或是圣诞节会不会突然跑出圣诞彩蛋。
Radix UI 毕竟还是比较小众的组件库,其星星数只有 3.4K 而已,比起 Shadcn UI 少了 10 几倍,如果遇到 bug 或是需要新功能时,能得到的社区资源相当有限
如果在会持续迭代的项目中使用 Shadcn UI 还有一个明显的缺点是“文档必须随着组件持续更新”,当我们使用较完整的组件库像是 Ant Design、MUI 等等,其组件的用法更新时会有官方负责维护文档,但我们使用 Shadcn UI 代表着多了一个可能会需要持续更新组件的成本。
可以简单总结为,如果 Radix 提供的组件功能可以符合需求,Shadcn UI 也能符合你的需求,不需要安装较重的 Ant Design。但是相对起来 Shadcn UI 需要维护的成本有可能会高一些,因为你需要维护所有的样式及文档。
简单的应用或是不会需要持续迭代的项目也许 Shadcn UI 满足你的需求,而且使用上也很简单;而 Ant Design 的功能很完善,对于如果是需要大型 form 或是 table 的应用,还有许多额外的功能,在复杂的应用中选择 Ant Design 是个不错的选择。
这是 Shadcn UI 提供的 form 代码片段,可以看到 form 使用了2次,为什么不是一个 form 呢?
export function ProfileForm() { // ... return ( <Form {...form}> <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-8"> <FormField control={form.control} name="username" render={({ field }) => ( <FormItem> <FormLabel>Username</FormLabel> <FormControl> <Input placeholder="shadcn" {...field} /> </FormControl> <FormDescription> This is your public display name. </FormDescription> <FormMessage /> </FormItem> )} /> <Button type="submit">Submit</Button> </form> </Form> )}
Shadcn UI 的 Form 封装并非基于 Radix UI 的 form,而是采用了 react-hook-form 进行封装。这可能会在名称上给人造成一定的混淆。
因为Radix UI 并没有 DatePicker组件,所以使用了 React DayPicker 组件。然而,该组件功能相对较少,不具备选择月份或年份的功能。
在 ReactDayPicker 的官方 GitHub 中,MonthPicker 功能已超出其范畴,若有此需求,可能需要自行制作。其想法较为简单,通过年份导航,“面板”将显示月份。另外,React DayPicker 依赖的是 date-fns,如果想要使用 dayjs,则需要考虑其他套件。
社区针对 Vue(3),也退出了对于的 vue 版本的 Shadcn,目前在 vite 下也能很好的使用。
如果你想使用 Unocss 代替 Tailwindcss,借助 unocss-preset-shadcn插件,也能很好的使用。
uno.config.ts:
import { presetShadcn } from 'unocss-preset-shadcn'export default defineConfig({ presets: [ presetShadcn({ color: 'neutral', radius: 0.5 }), ])}
components.json:
{ "$schema": "https://shadcn-vue.com/schema.json", "style": "default", "typescript": true, "tsConfigPath": ".nuxt/tsconfig.json", "tailwind": { "config": "tailwind.config.js", "css": "assets/styles/index.css", "baseColor": "neutral", "cssVariables": true }, "framework": "vite", "aliases": { "components": "~/components", "utils": "~/lib/utils", "ui": "~/components/ui" }}
你也可以在 nuxt 中使用,更多内容请查看: https://nuxt.com/modules/shadcn
看完这篇文章你应该可以了解 Shadcn UI 的有哪些特性,我们知道 Shadcn UI 跟许多的 UI 库不一样,它是通过源码的方式来使用,未来要修改样式都是由你自己决定,也这意味着你需要花更多精力去维护。
我们也知道了一些常见在技术选型中的问题,说到底 Shadcn UI 是 headless UI + Tailwind 的组合,在市面上还是有许多headless UI 的选择的,如果你要打造自己的组件库,可以选择一套headless UI 并且自己定制化。