如何使用TypeScript通过条件Props为元素设置不同CSS类?
如何使用TypeScript通过条件Props为元素设置不同CSS类?
Hey,我看到你遇到的问题啦——用条件判断给div加类名的时候,不仅代码重复得头疼,还出现了displayHeader条件不生效、类名混乱的情况,这大概率是因为多个条件同时满足,cx把所有符合的类都叠加上去了,加上重复的逻辑太多,很容易漏判或者冲突。咱们来一步步重构优化,让代码更清晰还解决问题:
核心优化思路
- 优先处理特殊场景:比如
cardBackground: "transparent"和bodyLayout: "no-image"这类优先级更高的场景,避免和普通条件冲突 - 提取公共变量:把
size对应的基础间距、displayHeader对应的内边距差异这些重复的逻辑抽出来,减少代码冗余 - 用函数封装类名生成逻辑:把复杂的条件判断封装成函数,让JSX里的代码更简洁,也方便后续维护
重构后的代码示例
首先,我们可以先定义几个辅助函数和变量,把重复的逻辑抽离:
// 根据size获取基础间距前缀 const getBaseSpacing = (size: "default" | "large") => size === "default" ? "px-5" : "px-6"; // 根据displayHeader和size获取头部相关的内边距 const getHeaderPadding = (displayHeader: boolean, size: "default" | "large") => { if (displayHeader) { return size === "default" ? "pb-5" : "pb-6"; } return size === "default" ? "pt-5 pb-5" : "pt-6 pb-6"; }; // 根据align和bodyLayout获取宽度/布局类 const getLayoutClasses = (align: "horizontal" | "vertical", bodyLayout?: "split" | "golden") => { if (align === "horizontal") { if (bodyLayout === "split") return "md:grow-0 md:shrink-0 md:basis-3/6"; if (bodyLayout === "golden") return "md:grow-0 md:shrink-0 md:basis-2/5"; } return "w-full"; };
第一个Div的类名重构
<div className={cx( // 优先处理特殊场景 { "hidden": bodyLayout === "no-image" }, { "p-0 w-full": cardBackground === "transparent", "md:grow-0 md:shrink-0 md:basis-3/6": cardBackground === "transparent" && align === "horizontal" && bodyLayout === "split", "md:grow-0 md:shrink-0 md:basis-2/5": cardBackground === "transparent" && align === "horizontal" && bodyLayout === "golden", }, // 普通场景:排除特殊情况后再应用 !cardBackground && bodyLayout !== "no-image" && cx( getBaseSpacing(size), getHeaderPadding(displayHeader, size), getLayoutClasses(align, bodyLayout), { "md:pl-5 md:pr-0": align === "horizontal" }, { "md:py-5": !displayHeader && align === "horizontal" } ), // 单独处理free-size场景 align === "horizontal" && bodyLayout === "free-size" && "px-5 md:pb-5 md:pl-5 md:pr-0 w-full h-auto md:w-[220px]" )} ></div>
第二个Div的类名重构
<div className={cx( "flex flex-col justify-center self-stretch flex-1", // 优先处理transparent场景 { "pt-3": cardBackground === "transparent", "md:pl-4": cardBackground === "transparent" && align === "horizontal" }, // 普通场景:排除transparent后应用 cardBackground !== "transparent" && cx( getBaseSpacing(size), // 根据场景判断内边距 align === "vertical" ? (displayHeader ? "pb-5 pt-3" : "pb-5") : cx( displayHeader ? (size === "default" ? "pb-5 pt-3 md:pb-5 md:pr-5 md:pl-4 md:pt-0" : "pb-6 pt-4 md:pb-6 md:pr-6 md:pl-5 md:pt-0") : (size === "default" ? "pb-5 pt-3 md:py-5 md:pr-5 md:pl-4 md:pt-0" : "pb-6 pt-4 md:py-6 md:pr-6 md:pl-5 md:pt-0"), // no-image场景的特殊处理 bodyLayout === "no-image" && (displayHeader ? (size === "default" ? "px-5 pb-5" : "px-6 md:pb-6") : (size === "default" ? "p-5" : "p-6")) ) ) )} ></div>
为什么这样优化?
- 优先级明确:先处理
transparent和no-image这类特殊场景,避免它们和普通条件的类名叠加冲突 - 减少冗余:把重复的size、displayHeader相关逻辑抽成函数,不用每次都写一长串条件
- 可读性更强:JSX里的类名逻辑变得简洁,后续修改某个场景的样式时,直接去对应函数里修改就行,不用在一堆条件里找
这样修改后,displayHeader的条件就能正确生效,也不会出现类名混乱的问题啦~
备注:内容来源于stack exchange,提问作者maria russo
相关产品推荐
相关产品推荐

