Shadcn UI, 最热门的前端开源技术

shadcn/ui 是 2023 年在 GitHub 上星星数量增长最多的项目,总共获得了 39.5k 的 star,而且在 2023 年 1 月的时候才在 GitHub 发布,接着 2024 年 3 月已经增长到 50K star,这个增长速度非常可怕,究竟它是靠什么让大家都愿意贡献给它一颗 star 呢?

目前一些热门的 UI 库,包括 MUIAnt DesignChakra 等等,然后就找到了这个 2023 年最热门的项目。刚开始看 Shadcn UI 组件的样式时并没有觉得令人惊艳,组件也跟其他 UI 库没什么不同,那为什么它会是 2023 年 star 增长数量最多的项目呢?

在这篇文章中会详细介绍 Shadcn UI,并且会整理一些在选择 Shadcn UI 大家会遇到的问题,提供给大家做技术选型的参考。

shadcn ui 简介

首先明确:Shadcn UI 不是 组件库

Shadcn UI 与常见的 MUI、Ant Design 和 Chakra 等等的组件库不一样,它并不是一个组件库,那它是什么呢?

实际上它是汇集了各种组件的一个项目,你可以选择需要的组件,然后复制粘贴到你的项目中。而且它没有 npm 包,这意味着你不会在 package.json 中看到 Shadcn UI。 看到它的使用方式,你可能会疑惑,这个和其他的组件库没有什么不同啊?

Shadcn UI 的底层是 Radix UI

Radix UI 是一个 headless 组件库,这表示它的组件没有任何的样式,它提供了可以定制化样式的方式,让我们自定义组件的样式。

此外,Radix UI 的所有组件都符合 WAI-ARIA 的要求,如果你需要建立具有可访问性的项目,Radix UI 无疑是一个好的选择。 另外一点,是 Radix UI 的所有组件都可以单独下载,你不用在一开始就安装整包的组件库,而是安装需要的组件到你的项目中即可:

bash 复制代码
npm install @radix-ui/react-dialog
npm install @radix-ui/react-dropdown-menu
npm install @radix-ui/react-tooltip

如果你不需要 Shadcn UI 提供的样式,也可以自己使用 Radix UI 封装成所需的组件库。

Shadcn UI 使用 Tailwind CSS 封装 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 CLI 下载组件到你的项目

Shadcn UI 的主要功能就是让你复制组件的源代码,它提供了 CLI 跟手动复制两种方式,使用 CLI 便可以很快速地将组件新增到你的项目中:

sql 复制代码
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 无法满足你的需求:

Radix UI 毕竟还是比较小众的组件库,其星星数只有 3.4K 而已,比起 Shadcn UI 少了 10 几倍,如果遇到 bug 或是需要新功能时,能得到的社区资源相当有限

  • 不想自己维护组件的文档:

如果在会持续迭代的项目中使用 Shadcn UI 还有一个明显的缺点是"文档必须随着组件持续更新",当我们使用较完整的组件库像是 Ant Design、MUI 等等,其组件的用法更新时会有官方负责维护文档,但我们使用 Shadcn UI 代表着多了一个可能会需要持续更新组件的成本。

Shadcn UI 跟 Ant Design 该怎么选

Ant Design 的优点:

  • 涵盖了非常广泛的使用者行为
  • form 系统很完善
  • 提供的组件非常多样化
  • 阿里旗下的套件,对于维护性毋庸置疑

Ant Design 的缺点:

  • 前几年发生了圣诞彩蛋事件 🥚
  • 功能多所以相对来说体积较大
  • 大版本经常会有 breaking change
  • 表格等部分组件性能不太好

Shadcn UI 的优点:

  • theme 的系统很完善,而且简单
  • 拥有高度定制化的弹性,因为你拥有了源代码
  • 较为轻量,你不用把所有的套件都安装到你的项目下
  • 符合 A11y 的规范

Shadcn UI 的缺点:

  • 未来的更新可能会比较辛苦一点,因为你拥有了所有的源代码,更新组件的同时可能需要同时维护文档
  • 组件较为简单,通常都需要自己再定制组件
  • 对于 table 等等有大量数据渲染的组件较弱
  • 对于复杂的表单,form的功能较弱

可以简单总结为,如果 Radix 提供的组件功能可以符合需求,Shadcn UI 也能符合你的需求,不需要安装较重的 Ant Design。但是相对起来 Shadcn UI 需要维护的成本有可能会高一些,因为你需要维护所有的样式及文档。

简单的应用或是不会需要持续迭代的项目也许 Shadcn UI 满足你的需求,而且使用上也很简单;而 Ant Design 的功能很完善,对于如果是需要大型 form 或是 table 的应用,还有许多额外的功能,在复杂的应用中选择 Ant Design 是个不错的选择。

其他在使用 Shadcn UI 遇到的问题

1.form 组件的结构有点怪

这是 Shadcn UI 提供的 form 代码片段,可以看到 form 使用了2次,为什么不是一个 form 呢?

javascript 复制代码
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 进行封装。这可能会在名称上给人造成一定的混淆。

2. 在 Shadcn UI 中,DatePicker 并非由 Radix UI 提供

因为Radix UI 并没有 DatePicker组件,所以使用了 React DayPicker 组件。然而,该组件功能相对较少,不具备选择月份或年份的功能。

在 ReactDayPicker 的官方 GitHub 中,MonthPicker 功能已超出其范畴,若有此需求,可能需要自行制作。其想法较为简单,通过年份导航,"面板"将显示月份。另外,React DayPicker 依赖的是 date-fns,如果想要使用 dayjs,则需要考虑其他套件。

Shadcn Vue

社区针对 Vue(3) ,也退出了对于的 vue 版本的 Shadcn,目前在 vite 下也能很好的使用。

Unocss

如果你想使用 Unocss 代替 Tailwindcss,借助 unocss-preset-shadcn插件,也能很好的使用。

uno.config.ts:

css 复制代码
import { presetShadcn } from 'unocss-preset-shadcn'

export default defineConfig({
  presets: [
    presetShadcn({
      color: 'neutral',
      radius: 0.5
    }),
  ]
)}

components.json:

bash 复制代码
{
  "$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 并且自己定制化。

相关推荐
编程零零七2 小时前
Python数据分析工具(三):pymssql的用法
开发语言·前端·数据库·python·oracle·数据分析·pymssql
(⊙o⊙)~哦4 小时前
JavaScript substring() 方法
前端
无心使然云中漫步4 小时前
GIS OGC之WMTS地图服务,通过Capabilities XML描述文档,获取matrixIds,origin,计算resolutions
前端·javascript
Bug缔造者4 小时前
Element-ui el-table 全局表格排序
前端·javascript·vue.js
xnian_5 小时前
解决ruoyi-vue-pro-master框架引入报错,启动报错问题
前端·javascript·vue.js
罗政5 小时前
[附源码]超简洁个人博客网站搭建+SpringBoot+Vue前后端分离
vue.js·spring boot·后端
麒麟而非淇淋5 小时前
AJAX 入门 day1
前端·javascript·ajax
2401_858120536 小时前
深入理解MATLAB中的事件处理机制
前端·javascript·matlab
阿树梢6 小时前
【Vue】VueRouter路由
前端·javascript·vue.js
随笔写7 小时前
vue使用关于speak-tss插件的详细介绍
前端·javascript·vue.js