cat cafe at Catfel Tower使用 React 和 TypeScript 制作动态可复用组件由于 React 和 TypeScript 的技术组合越来越受欢迎,我们将利用 Tailwind 制作一些酷炫的可复用按钮 。
在此过程中,我们还将了解一些非常小的库来帮助我们:
- Class-variance-authority 是一个用于制作可复用类的库 , 特别适合于 Tailwind,因为我们不需要在它之外定义任何东西 —— 一个安全、始终有效的工具!
- Tailwind-merge 和 clsx 是两个帮助我们管理我们在 class-variance-authority 定义中定义的类的库 。它们的使用完全是可选的,因为它们只在一些罕见的情况下有用 。
npm i tailwind-merge clsx class-variance-authority首先,我们创建一个名为 Button.tsx 的文件,其中包含一个基本的按钮组件:export const Button = () => {return (<button></button>);};然后,我们用 class-variance-authority 定义我们的类 。为此,从库中导入函数 , 如下所示:import { cva } from "class-variance-authority";函数接受两个参数:- 适用于我们可复用按钮所有变体的基本类
- 包括我们定义的变体及其基本回退情况的对象(以防我们忘记定义某些内容) 。
export const buttonVariants = cva("text-black transition-all border-[1px] border-solid focus:ring-2 text-small",{variants: {variant: {filled: "bg-yellow-600 ring-black border-yellow-600 hover:bg-white",outline: "border-yellow-600 ring-black bg-white hover:bg-yellow-600",},size: {small: "px-[1.5rem] py-[1rem] rounded-sm",medium: "px-[2rem] py-[1.5rem] rounded-md",},},defaultVariants: {variant: "filled",size: "small",},});然后 , 我们定义默认变体:variant 将是 filled,size 将是 small 。由于我们的组件是可复用的,我们需要以某种方式将这些属性传递给它 —— 我们将通过 props 来做,并使它们类型安全 。
首先,我们将声明一个基本接口:
interface IButtonProps {}然后,我们将从 class-variance-authority 的泛型接口 VariantProps 扩展,可以通过 cva 函数导入它 。它接受我们定义的 buttonVariants 的 typeof 并使 props 类型安全,因此我们不会定义我们没有的 big 尺寸:interface IButtonProps extends VariantProps<typeof buttonVariants> {}最后,我们还将从 React 的 HTMLAttributes 扩展,它也是泛型并接受 HTML 元素的类型 。它将使我们的 props 包括按钮的所有基本 HTML 属性 , 如 onClick,以及我们类型中定义的 React children:interface IButtonPropsextends HTMLAttributes<HTMLButtonElement>,VariantProps<typeof buttonVariants> {}完成所有这些后,我们可以这样对组件进行类型化并使用其 props:export const Button = ({variant,size,className,children,...props}: IButtonProps) => {return (<button className={buttonVariants({ size, variant })} {...props}>{children}</button>);};现在 , 当我们传递 variant 和 size 时,按钮将改变其视图!看:export default function App() {return (<><Button variant="filled">填充按钮</Button><Button variant="outline">轮廓按钮</Button></>);}但是 , 当我们需要稍微调整按钮时怎么办?为此,我们有我们的 className 属性 , 可以用两种不同的方式使用:我们在现场将其与我们的 buttonVariants 函数合并,使用模板字面量:
<button className={`${buttonVariants({ size, variant })} ${className}`} {...props}>我们使用之前提到的两个库来确保我们的类没有重复:例如,当我们有 mx-2 和 my-2 时,它将被转换为 m-2 。为此,让我们在其他地方定义一个小函数,如下所示:
import clsx, { ClassValue } from "clsx";import { twMerge } from "tailwind-merge";export const clsxm = (...classes: ClassValue[]) => twMerge(clsx(...classes));这里 , 它接受任何数量的类并将它们与 tailwind-merge 库中的函数合并 。现在,我们可以用该函数而不是模板字面量合并我们的类:
推荐阅读
- 如何清理垃圾让手机变得更流畅 清理手机垃圾的方法有哪些
- 挨饿和运动,哪种减肥方式更靠谱?
- 王者荣耀:最强打野教学,让你不再迷茫!
- 为什么站着更耗费体力
- 更的偏旁部首是什么 更的偏旁部首
- 周冬雨疑似微调,眼皮比以前更深了,脸颊更丰满,没有之前的气质
- cdr应该咋的才能更改尺寸
- TVB花旦陈茵媺自曝复出压力大,更拒绝再与老公合作,望孩子支持
- 如何预防口腔溃疡?这7种措施让你远离口腔溃疡!
- 如何更改打印机端口,如何添加打印服务器端口
