2023年最火前端項目憑什么是它?
近日,JavaScript Rising Stars 正式公布 2023 年 JavaScript 明星項目榜單,其中 shadcn/ui 位列榜首,2023 年獲得了 39.5k Star。本文將深入探討 shadcn/ui 是什么、使用方式、實現原理,它憑什么能夠成為年度最火前端項目!
概述
Shadcn UI 與其他 UI 和組件庫如 Material UI、Ant Design、Element UI 的設計理念截然不同。這些庫一般通過 npm 包提供對組件的訪問,而 Shadcn UI 允許用戶將單個 UI 組件的源代碼直接下載到項目中,提供了更大的靈活性和定制空間。
按照 Shadcn UI 的說法,Shadcn UI 實際上并不是一個組件庫,而是可以復制并粘貼到應用中的可重用組件的集合。
不到一年的時間,Shadcn UI 在 Github 上獲得了超過 40k Star。
Shadcn UI 相比其他組件庫提供了幾個顯著的優(yōu)勢,其中最突出的包括:
- 簡潔且易于使用:Shadcn UI為用戶提供了直觀且易于理解的文檔,可以輕松地開始使用。它不需要復雜的配置步驟,只需簡單的復制粘貼或使用CLI安裝即可快速集成到項目中。與其他組件庫相比,Shadcn UI簡化了開發(fā)流程,降低了學習曲線,可以專注于構建應用的核心功能。
- 卓越的可訪問性:Shadcn UI 在設計之初就充分考慮到了可訪問性,確保其組件符合Web內容可訪問性指南(WCAG)標準。這意味著使用Shadcn UI構建的應用程序不僅外觀美觀,而且能夠適應各種用戶需求,無論是使用屏幕閱讀器、鍵盤導航還是其他輔助技術的用戶都能順利使用。
- 精細控制與高度可定制:與其他UI庫不同,Shadcn UI允許直接訪問每個組件的源代碼。這意味著可以根據項目的具體需求輕松調整代碼,而無需受限于預定義的模板或樣式。這種高度的定制性提供了更大的靈活性,可以輕松地調整組件的外觀、行為和功能,以滿足項目的獨特要求。此外,這種可定制性還簡化了應用 的擴展和維護工作,使得長期開發(fā)變得更加高效。
在決定是否在未來的項目中采用Shadcn UI之前,有幾個關鍵因素值得考慮:
- 安裝與配置:使用Shadcn UI可能需要一些手動工作。由于您需要單獨安裝或復制每個所需的組件,對于那些習慣于自動化的現代開發(fā)環(huán)境的人來說,這可能意味著額外的步驟和潛在的混亂。對于那些希望快速集成UI庫的人來說,這可能是一個挑戰(zhàn)。
- 代碼庫大小與可維護性:Shadcn UI的直接源代碼訪問意味著您的項目代碼庫可能會增加,因為您需要包含每個組件的完整代碼。這可能會導致代碼行數增加,從而影響項目的可維護性和性能。對于大型項目或長期開發(fā)來說,這可能是一個重要的考慮因素。
- 定制與擴展性:雖然Shadcn UI的直接源代碼訪問提供了高度定制化的機會,但這也意味著你可能需要更多的時間和資源來調整和擴展組件。對于需要高度定制化和靈活性的項目,這是一個優(yōu)點;但對于需要快速集成的簡單應用程序,這可能不是最佳選擇。
- 社區(qū)與支持:隨著時間的推移,一個活躍的社區(qū)和良好的支持是確保庫持續(xù)發(fā)展和更新的關鍵因素。Shadcn UI的社區(qū)規(guī)模和活躍度可能與更成熟的庫相比較少。因此,評估其社區(qū)的成熟度和可用資源是決定是否采用Shadcn UI的重要考慮因素。
功能
Shadcn UI 提供了很多功能,以增強用戶體驗。下面就來看看 Shadcn UI 中的幾個主要的功能:主題和主題編輯器、暗黑模式、CLI和組件。
主題和主題編輯器
Shadcn UI 提供了精選的主題,可以輕松地將其復制并粘貼到應用程序中??梢赃x擇通過代碼庫手動添加主題標記,或者使用 Shadcn UI 的主題編輯器進行更方便的操作。
主題編輯器允許配置各種屬性,如顏色、邊框半徑和模式(明亮或暗黑)。此外,還可以選擇兩種樣式:默認樣式和紐約樣式。每種樣式都具有獨特的組件、動畫和圖標。默認樣式具有較大的輸入字段、lucide-react圖標和用于動畫效果的tailwindcss-animate。而紐約樣式則包括較小的按鈕、帶陰影的卡片和Radix圖標。
使用Shadcn UI的圖形界面,創(chuàng)建自定義主題也非常簡單。編輯器會生成包含自定義樣式定義的代碼片段,只需將其復制粘貼到應用中即可。
shadcn-ui-theme-editor.gif下面是主題編輯器的代碼輸出示例,提供了淺色模式和深色模式的樣式標記:
@layer base {
:root {
--background: 0 0% 100%;
--foreground: 222.2 84% 4.9%;
--card: 0 0% 100%;
--card-foreground: 222.2 84% 4.9%;
--popover: 0 0% 100%;
--popover-foreground: 222.2 84% 4.9%;
--primary: 221.2 83.2% 53.3%;
--primary-foreground: 210 40% 98%;
--secondary: 210 40% 96.1%;
--secondary-foreground: 222.2 47.4% 11.2%;
--muted: 210 40% 96.1%;
--muted-foreground: 215.4 16.3% 46.9%;
--accent: 210 40% 96.1%;
--accent-foreground: 222.2 47.4% 11.2%;
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 210 40% 98%;
--border: 214.3 31.8% 91.4%;
--input: 214.3 31.8% 91.4%;
--ring: 221.2 83.2% 53.3%;
--radius: 0.3rem;
}
.dark {
--background: 222.2 84% 4.9%;
--foreground: 210 40% 98%;
--card: 222.2 84% 4.9%;
--card-foreground: 210 40% 98%;
--popover: 222.2 84% 4.9%;
--popover-foreground: 210 40% 98%;
--primary: 217.2 91.2% 59.8%;
--primary-foreground: 222.2 47.4% 11.2%;
--secondary: 217.2 32.6% 17.5%;
--secondary-foreground: 210 40% 98%;
--muted: 217.2 32.6% 17.5%;
--muted-foreground: 215 20.2% 65.1%;
--accent: 217.2 32.6% 17.5%;
--accent-foreground: 210 40% 98%;
--destructive: 0 62.8% 30.6%;
--destructive-foreground: 210 40% 98%;
--border: 217.2 32.6% 17.5%;
--input: 217.2 32.6% 17.5%;
--ring: 224.3 76.3% 48%;
}
}
暗黑模式
Shadcn UI 支持 Next.js 和 Vite 應用的暗黑模式。對于 Next.js 應用,Shadcn UI 使用next-themes
來實現暗黑模式切換功能。當用戶在明亮模式和暗黑模式之間切換時,應用會在明亮和暗黑主題標記之間進行切換。
CLI
Shadcn UI 的 CLI 可以將庫與應用集成,并添加依賴項以及應用相關的tailwind.config.js
配置。使用CLI還可以輕松地向應用程序添加UI組件。
可以選擇手動從文檔中復制和粘貼每個組件的代碼,或者使用CLI進行添加。CLI提供了優(yōu)秀的開發(fā)者體驗,是使Shadcn UI更易于使用的一個功能。
組件
截至目前,Shadcn UI 擁有 40 個組件,包括 Accordion(手風琴)、Skeleton(骨架屏)、Table(表格)和Popover(彈出框)等。通過利用 Shadcn UI 預構建的組件,可以節(jié)省時間,而不必從頭開始構建組件。
使用
下面來看看如何將 Shadcn UI 與 Next.js 集成。
初始化
首先,通過運行以下命令創(chuàng)建一個新的 Next.js 應用:
npx create-next-app@latest my-app --typescript --tailwind --eslint
接下來,運行 init 命令來初始化新項目的依賴項:
npx shadcn-ui@latest init
CLI 將提示進行一些配置。以下是配置問題的示例:
Would you like to use TypeScript (recommended)? no / yes
Which style would you like to use? ? Default
Which color would you like to use as base color? ? Slate
Where is your global CSS file? ? ? app/globals.css
Do you want to use CSS variables for colors? ? no / yes
Where is your tailwind.config.js located? ? tailwind.config.js
Configure the import alias for components: ? @/components
Configure the import alias for utils: ? @/lib/utils
Are you using React Server Components? ? no / yes
現在就可以在應用中添加組件了,下面就來添加一個按鈕組件。
添加按鈕
可以運行以下命令以使用 CLI 添加一個按鈕:
npx shadcn-ui@latest add button
CLI 會自動創(chuàng)建一個組件文件夾,只需要從文件夾中導出它:
import { Button } from "@/components/ui/button"
<Button variant="outline">Button</Button>
按鈕組件的 variant 屬性有六種值:default、destructive、outline、secondary、ghost、link。
創(chuàng)建表單
Shadcn UI 在表單方面不僅提供了 Input、Textarea、Checkbox 和 RadioGroup 等表單組件,還提供了一個Form組件,該組件是 react-hook-form 的包裝器。下面來用 shadcn/ui 創(chuàng)建一個登錄表單。
Form 組件提供了一些功能:
- <FormField /> 組件,用于構建受控表單字段
- 支持使用表單驗證庫(如Valibot、Yup和Zod)進行驗證
- 錯誤消息處理
可以運行以下命令來使用表單組件:
npx shadcn-ui@latest add form input
接下來,添加表單組件:
// use client
import { zodResolver } from "@hookform/resolvers/zod";
import { useForm } from "react-hook-form";
import * as z from "zod";
import { Button } from "@/components/ui/button";
import {
Form,
FormControl,
FormDescription,
FormField,
FormItem,
FormLabel,
FormMessage,
} from "@/components/ui/form";
import { Input } from "@/components/ui/input";
const FormSchema = z.object({
username: z.string().min(2, { message: "用戶名至少兩個字" }),
});
export function InputForm() {
const form = useForm({ resolver: zodResolver(FormSchema) });
function onSubmit(data) {
return (
<pre className="mt-2 w-[340px] rounded-md bg-slate-950 p-4">
{JSON.stringify(data, null, 2)}
</pre>
);
}
return (
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="w-2/3 space-y-6">
<FormField control={form.control} name="username" render={({ field }) => (
<FormItem>
<FormLabel>Username</FormLabel>
<FormControl>
<Input placeholder="Input username" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)} />
<Button type="submit">Submit</Button>
</form>
</Form>
);
}
原理
Shadcn UI 組件的通用架構如下:
shadcn/ui基于核心原則構建,即組件的設計應與其實現分開。因此,shadcn/ui中的每個組件都具有兩層架構。即:
- 結構和行為層
- 樣式層
結構和行為層
在結構和行為層,組件以無頭形式實現,這意味著它們的結構組成和核心行為都被封裝在相應的表示中,這意味著組件的結構、布局和核心功能都在這一層進行定義和實現。此外,對于一些復雜的交互,如鍵盤導航和WAI-ARIA標準兼容性,也在這個層面進行考慮和實現。
為了支持這些復雜的功能和交互,shadcn/ui借助了一些成熟的、無頭(無界面)的UI庫。Radix UI 就是其中的一個關鍵庫,它在shadcn/ui的代碼庫中占有重要地位。許多常見的組件,如折疊面板(Accordion)、彈出框(Popover)、選項卡(Tabs)等,都是基于 Radix UI 的實現構建的。
對于滿足大多數組件需求,原生瀏覽器元素和Radix UI組件已經足夠了。但在某些情況下,需要使用更專業(yè)的無頭UI庫來滿足特定需求。
其中一種情況是表單處理。為了處理表單,shadcn/ui提供了一個基于React Hook Form無頭表單庫的Form組件。這個組件負責管理表單的狀態(tài),而shadcn/ui則通過組合的方式,利用React Hook Form提供的基元進行了進一步的封裝。
對于表格視圖的處理,shadcn/ui 選擇了 Tanstack React Table 這個無頭表格庫。它的Table
和DataTable
組件都是基于這個庫構建的。Tanstack React Table 提供了豐富的 API,用于處理表格視圖的各種交互,如過濾、排序和虛擬化。
另外,對于一些復雜的日期選擇組件,如日歷視圖、DateTime選擇器和DateRange選擇器,shadcn/ui 選擇了 React Day Picker 這個庫作為基礎組件,以實現這些組件的無頭層。這些組件往往難以正確實現,但通過使用 React Day Picker, shadcn/ui 確保了它們的正確性和易用性。
樣式層
TailwindCSS 是 shadcn/ui 樣式層的核心。顏色、邊框半徑等屬性值作為CSS變量存放在global.css文件中,以便于全局管理。這些變量可以跨設計系統(tǒng)共享,使用 Figma 等設計工具時,可以追蹤并同步Figma的變量。
為了區(qū)分組件的樣式,shadcn/ui引入了Class Variance Authority(CVA)。CVA提供了一個強大的API,允許我們?yōu)槊總€組件定制其樣式。
shadcn/ui Badge
在探討了 shadcn/ui 的架構后,下面來深入了解一些組件的具體實現,先從最簡單的組件開始。
import * as React from "react";
import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "@/lib/utils";
const badgeVariants = cva(
"inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
{
variants: {
variant: {
default: "border-transparent bg-primary text-primary-foreground hover:bg-primary/80",
secondary: "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
destructive: "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
outline: "text-foreground",
},
},
defaultVariants: {
variant: "default",
},
}
);
export interface BadgeProps extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof badgeVariants> {}
function Badge({ className, variant, ...props }: BadgeProps) {
return <div className={cn(badgeVariants({ variant }), className)} {...props} />;
}
export { Badge, badgeVariants };
組件的實現始于對 class-variance-authority 中的 cva
函數的調用,它被用于聲明組件的不同變體。
const badgeVariants = cva(
"inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
{
variants: {
variant: {
default: "border-transparent bg-primary text-primary-foreground hover:bg-primary/80",
secondary: "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
destructive: "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
outline: "text-foreground",
},
},
defaultVariants: {
variant: "default",
},
}
);
cva函數的第一個參數為<Badge/>組件的所有變體定義了基本樣式。作為第二個參數,cva接收一個配置對象,該對象規(guī)定了組件的可能變體以及應使用的默認變體。需要注意的是,實用樣式采用了tailwind.config.js中定義的設計系統(tǒng)標記,這使得只需調整 CSS 變量,就能輕松更新整體的外觀。
調用cva函數后會返回另一個函數,該函數可根據條件為各個變體應用相應的樣式。將其存儲在名為badgeVariants的變量中,以便在向組件傳遞變體名稱作為屬性時,能夠利用它應用正確的樣式。
接下來,我們可以找到定義組件類型的BadgeProps接口:
export interface BadgeProps extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof badgeVariants> {}
Badge 組件基于HTML的div元素。為了方便使用,該組件被設計為div元素的擴展。這一目標通過擴展React.HTMLAttributes<HTMLDivElement>類型來實現。此外,為了滿足不同需求,組件添加了一個variant屬性,允許使用者選擇并呈現所需的組件變體。VariantProps這一輔助類型以枚舉的形式在variant屬性上呈現可用的變體,進一步增強了組件的靈活性和易用性。
function Badge({ className, variant, ...props }: BadgeProps) {
return <div className={cn(badgeVariants({ variant }), className)} {...props} />;
}
最終,我們得到了定義 Badge 的函數組件。在此組件中,除了 className 和 variant 之外的所有 props 都被收集到一個對象中,并通過擴展語法傳遞給底層的 div 元素。這使得組件使用者能夠與 div 元素上可用的所有 props 進行交互。
值得注意的是,組件中處理樣式應用的方式。variant 的值被傳遞到 badgeVariants 函數中,該函數返回一個包含渲染組件變體所需的所有實用程序類名的 class 字符串。此外,還有一個名為 cn 的函數,它將前述函數的返回值和傳遞到 className 中的值合并,然后計算為 div 元素的 className 屬性。
cn 函數是 shadcn/ui 提供的一個特殊實用函數,用于管理實用程序類。接下來,我們將深入探討它的實現。
import { type ClassValue, clsx } from "clsx";
import { twMerge } from "tailwind-merge";
function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
這個實用函數是兩個庫的結合體,用于管理實用程序類。第一個庫是 clsx
。它提供了通過 className
連接來有條件地應用樣式到組件的能力。
import React from "react";
const Link = ({ isActive, children }: { isActive: boolean, children: React.ReactNode }) => {
return <a className={clsx("text-lg", { "text-blue-500": isActive })}>{children}</a>;
};
從上述代碼中可以看到 clsx 獨立使用的情形。在默認情況下,只有 text-lg 實用類被應用于 Link 組件。但當將 isActive 屬性傳遞給組件并設置為 true 時,text-blue-500 實用類也會被應用于該組件。
然而,在某些情況下,僅使用 clsx 無法實現我們的目標。
import React from "react";
import clsx from "clsx";
const Link = ({ isActive, children }: { isActive: boolean, children: React.ReactNode }) => {
return <a className={clsx("text-lg text-grey-800", { "text-blue-500": isActive })}> {children}</a>;
};
在此情況下,元素默認應用了顏色實用類 text-grey-800。我們的目標是在 isActive 變?yōu)?nbsp;true 時將文本顏色更改為 blue-500。但由于 CSS 的層疊性質,Tailwind 中的 text-grey-800 應用的顏色樣式無法被修改。
此時就需要使用 tailwind-merge庫。使用 tailwind-merge 修改上述代碼:
import React from "react";
import { twMerge } from "tailwind-merge";
import clsx from "clsx";
const Link = ({ isActive, children }: { isActive: boolean, children: React.ReactNode }) => {
return <a className={twMerge(clsx("text-lg text-grey-800", { "text-blue-500": isActive }))}>{children}</a>;
};
clsx的輸出現在將通過tailwind-merge進行處理。tailwind-merge將解析類字符串并進行淺層樣式定義合并。這意味著text-grey-800被替換為text-blue-500,從而確保元素能體現出新的條件樣式應用。
這種方法有助于確保在實現變體時不會發(fā)生任何樣式沖突。由于className屬性也經過了cn工具的處理,如果需要,可以輕松覆蓋任何樣式。但這也存在一個權衡之處。使用cn開啟了組件使用者臨時覆蓋樣式的可能性。這將使一定程度的責任轉移到代碼審查步驟上,以驗證cn沒有被濫用。另一方面,如果根本不需要啟用這種行為,可以修改組件僅使用clsx。
在分析Badge組件的實現時,可以發(fā)現一些與 SOLID 原則相關的模式:
- 單一職責原則: Badge 組件專注于一個職責,即根據提供的變體渲染不同樣式的徽章,并將樣式管理委托給了 badgeVariants 對象。
- 開放/封閉原則: 代碼符合開放/封閉原則,允許添加新的變體而無需修改現有代碼。可以輕松地將新的變體添加到 badgeVariants 定義中的變體對象中。但需要注意的是,由于 cn 的使用方式,組件使用者可以通過 className 屬性傳遞新的覆蓋樣式。這可能會使組件對修改開放。因此,在構建自己的組件庫時,需要決定是否應允許這種行為。
- 依賴倒置原則: Badge 組件及其樣式是分別定義的。Badge 組件依賴于 badgeVariants 對象獲取樣式信息。這種分離提供了靈活性和更容易的維護,符合依賴倒置原則。
- 一致性和可重用性: 代碼通過使用實用函數 cva 來根據變體管理和應用樣式來促進一致性。這種一致性可以使開發(fā)人員更容易理解和使用組件。此外,Badge 組件是可重用的,可以輕松地集成到應用的不同部分中。
- 關注點分離: 樣式和渲染的關注點被分開。badgeVariants 對象處理樣式邏輯,而 Badge 組件負責渲染和應用樣式。
在分析了 Badge 組件的實現之后,我們對 shadcn/ui 的一般架構有了更詳細的了解。但這是一個純顯示級別的組件。下面來看看其他一些交互式組件。
shadcn/ui Switch
下面是 Switch 組件的具體實現:
import * as React from "react"
import * as SwitchPrimitives from "@radix-ui/react-switch"
import { cn } from "@/lib/utils"
const Switch = React.forwardRef<
React.ElementRef<typeof SwitchPrimitives.Root>,
React.ComponentPropsWithoutRef<typeof SwitchPrimitives.Root>
>(({ className, ...props }, ref) => (
<SwitchPrimitives.Root
className={cn(
"peer inline-flex h-6 w-11 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input",
className
)}
{...props}
ref={ref}
>
<SwitchPrimitives.Thumb
className={cn(
"pointer-events-none block h-5 w-5 rounded-full bg-background shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-5 data-[state=unchecked]:translate-x-0"
)}
/>
</SwitchPrimitives.Root>
))
Switch.displayName = SwitchPrimitives.Root.displayName
export { Switch }
Switch 組件是用于在兩個選項之間進行選擇的交互式組件,與僅用于顯示的 Badge 組件不同。Switch 組件能夠響應用戶的操作并切換其狀態(tài),為用戶提供即時的反饋。
用戶與開關的交互主要通過點擊實現。構建一個能夠響應指針事件的開關相對簡單,但要使其也能響應鍵盤輸入和屏幕閱讀器,實現起來就更為復雜。以下是開關組件的一些預期行為:
- 當用戶使用 Tab 鍵在界面上移動時,Switch 應該能接收焦點。
- 一旦獲得焦點,用戶按下 Enter 鍵將觸發(fā)開關狀態(tài)的切換。
- 在使用屏幕閱讀器的情況下,Switch 應能向用戶清晰地傳達其當前狀態(tài)。
在代碼中,可以看到開關的實際結構是通過使用 <SwitchPrimitives.Root/> 和 <SwitchPrimitives.Thumb/> 復合組件構建而成。這些組件來自 RadixUI 無頭庫,包含了開關的預期行為的所有實現。通過 React.forwardRef 進行構建,使得組件能夠與傳入的 ref 綁定,這在需要跟蹤焦點狀態(tài)并與外部庫集成時非常有用。
值得注意的是,RadixUI 組件沒有提供任何樣式。因此,經過 cn 實用函數處理后,樣式直接應用于該組件的 className 屬性上。如有需要,還可以使用 cva 為組件創(chuàng)建變體。這種靈活的樣式管理方式使得開發(fā)者能夠根據項目需求進行定制化設計,提高用戶體驗。
小結
這里我們討論了 shadcn/ui 的一般架構,這種實現方式同樣應用在 shadcn/ui 的其它組件中。不過,某些組件的行為和實現會稍微復雜一些,比如:
- Calendar
- 使用 react-day-picker 作為無頭組件。
- 使用 date-fns 作為日期時間格式化庫。
- Table 和 DataTable
- 使用 @tanstack/react-table 作為無頭表格庫。
- Form
- 使用 react-hook-form 作為表單和表單狀態(tài)管理庫的無頭組件。
- shadcn/ui 提供了封裝表單邏輯的實用組件,可用于組裝表單的各個部分,包括輸入和錯誤消息。
- 表單的模式驗證庫使用 zod。zod 返回的驗證錯誤被傳遞到 <FormMessage/> 組件,在表單輸入旁邊顯示錯誤信息。
shadcn/ui 在前端開發(fā)領域中引入了一種創(chuàng)新的范例。它倡導一種新的思維方式,即開發(fā)者可以擁有組件的實現權,而不僅僅是依賴于抽象化的第三方包。通過這種方式,開發(fā)者能夠僅暴露所需的元素,從而更好地控制組件的行為和外觀。
在應用設計系統(tǒng)時,shadcn/ui 鼓勵開發(fā)者跳出預先構建的組件庫所限制的固定 API 表面。相反,它鼓勵開發(fā)者構建自己的設計系統(tǒng),并提供足夠良好的默認設置,以便開發(fā)者可以根據自己的需求進行自定義。這種靈活性使得開發(fā)者能夠更好地適應不同的項目需求,并在設計過程中擁有更大的自由度。
總結
Shadcn UI 為開發(fā)者提供了一種全新的體驗,與現有的組件庫相比,它如一陣清風般令人耳目一新。它不僅加快了開發(fā)速度,還為開發(fā)者提供了對組件的精細控制,使他們能夠創(chuàng)造出獨特且富有創(chuàng)意的用戶界面。
當然,沒有任何庫能滿足所有需求,但基于當前的行業(yè)趨勢,Shadcn UI 無疑已成為前端生態(tài)系統(tǒng)中的佼佼者。許多大型公司,如 Vercel,已經采納了這一解決方案。例如,Vercel 的 v0 應用利用 Shadcn UI、Tailwind CSS 等來生成 UI 代碼,這些代碼可供開發(fā)人員直接復制并粘貼到其項目中。
盡管 Shadcn UI 仍是一個相對較新的工具,但隨著時間的推移,期待看到其功能和組件的進一步豐富和完善。你是否會考慮在未來的項目中采用 Shadcn UI 呢?