当前位置: 首页 > news >正文

做中后台业务,为什么我不建议你用 Tailwind CSS?

大家好,我又来了😁

最近我接手了一个隔壁组转过来的中后台重构项目。

交接的时候,对方的技术负责人特意跟我强调,说这个项目采用了最新的技术栈,全面拥抱了
,Tailwind CSS开发体验极其丝滑。

我当时心里还挺期待,毕竟这两年Tailwind的风刮得太大了,各种国内外大佬都在疯狂带货。结果周末我抽空把代码拉下来,打开VSCode准备梳理一下业务主流程。盯了屏幕不到十分钟,我感觉自己的眼睛快瞎了。

光说理论没意思,我直接给你们截取一段真实的、承载了各种表单校验和状态联动的业务侧边栏组件。你们自己品鉴一下所谓的极致开发体验👇:

const OrderCard = ({ order, isAdmin, isExpanded }) => { return ( <div className={`flex flex-col w-full p-5 mb-4 border rounded-lg shadow-sm transition-all duration-300 ${ isAdmin ? 'bg-red-50 border-red-200' : 'bg-white border-gray-200' } ${ isExpanded ? 'max-h-[800px]' : 'max-h-24 overflow-hidden' } hover:shadow-md cursor-pointer`} > <div className='flex items-center justify-between pb-3 mb-3 border-b border-gray-100'> <span className='text-sm font-semibold text-gray-800 truncate w-[60%]'> {order.id} </span> <span className={`px-2 py-1 text-xs rounded-full ${ order.status === 'PAID' ? 'bg-green-100 text-green-700' : 'bg-orange-100 text-orange-700' }`} > {order.statusText} </span> </div> {/* 内部极其复杂的业务字段渲染... */} </div> ); }

代码跑得通吗?当然跑得通。UI 还原度高吗?也挺高。 但是作为接下来要维护这个项目的组长,我只觉得一阵头皮发麻。

很多前端新人,甚至是做惯了C 端独立开发的兄弟,对Tailwind简直是顶礼膜拜。因为它不用取名字,不用在JSCSS文件之间来回切换,写起来确实有快感。

但作为趟过无数中后台项目的深水区,我今天必须给这股跟风热潮泼一盆冷水:在绝大多数重型中后台业务场景里,Tailwind CSS并不是什么神兵利器,而是给后期维护带来不方便。

来,咱们拿真实代码说话,看看它到底是怎么摧毁中后台工程的👇。

彻底掩盖你的业务主线?

做中后台系统,最难的从来不是画 UI,而是处理极度复杂的数据状态流转。

上面那段代码最大的问题在于信噪比极低。作为一个接手代码的前端,我点开这个文件,首先想看的是:这个组件在不同权限、不同展开状态下,业务逻辑是怎么走的?

但在Tailwind的体系下,我的视线全被flexp-5mb-4max-h-[800px]这种毫无业务价值的视觉原子类给强暴了。如果退回到老古董的CSS Modules方案,这段代码在JS侧应该长什么样?咱们对比一下:

import classNames from 'classnames'; import styles from './OrderCard.module.less'; const OrderCard = ({ order, isAdmin, isExpanded }) => { return ( <div className={classNames(styles.orderCard, {[styles.adminMode]: isAdmin, [styles.expanded]: isExpanded })} > <div className={styles.cardHeader}> <span className={styles.orderId}>{order.id}</span> <span className={classNames(styles.statusBadge, { [styles.statusPaid]: order.status === 'PAID', [styles.statusPending]: order.status === 'PENDING' })} > {order.statusText} </span> </div> {/* 业务字段一目了然 */} </div> ); }

发现区别了吗?重构后的JSX变得极其纯粹。我只通过adminModeexpanded这种类名,就极其清晰地传达了业务语义。至于那个订单编号到底占百分之几十的宽度,那是UI 层该关心的事情,它安静地待在.less文件里,绝不会来污染我的业务主逻辑。

跟现成的组件库水土不服

中后台业务是不可能脱离Ant Design
、Element Plus
这类重型组件库的。而组件库的本质,是封装好了一整套内部的DOM结构和ClassName规范。

这就带来了一个极其致命的冲突:当你用Tailwind去覆盖Ant Design的内部样式时,你会写出极其恶心的Hack代码😖。

比如产品经理要求:在这个特定页面里,把Ant Design表格的表头背景色改成浅蓝色,单元格的padding改小一点。

正常的Less做法是用样式穿透,精确打击:

/* 样式文件覆盖 */ .myCustomTable { :deep(.ant-table-thead > tr > th) { background-color: #f0f8ff; padding: 8px 16px; } }

你知道那个拥抱Tailwind的小伙子是怎么写的吗?为了不写CSS文件,他强行使用了Tailwind v3+的任意变体语法:

// Tailwind 强行覆盖组件库内部样式 <Table className='[&_.ant-table-thead>tr>th]:bg-blue-50[&_.ant-table-thead>tr>th]:py-2 [&_.ant-table-thead>tr>th]:px-4 [&_.ant-table-tbody>tr>td]:text-gray-600[&_.ant-table-tbody>tr>td]:py-2' dataSource={data} columns={columns} />

这段代码合进主分支的时候,我都替后续维护的兄弟感到悲哀😢。

这玩意儿连换行都没有,密密麻麻挤在一起。未来如果要做主题切换,或者升级Ant Design导致内部类名变了,谁敢去动这坨连正则都极难匹配的字符串?

不仅没有提高开发效率,反而为了强行凑Tailwind的语法,写出了一堆极难维护的代码。


负边距引发的问题

一行代码被写出来的成本,远远低于它在未来三年里被维护的成本。

Tailwind本质上就是披着ClassName外衣的行内样式。它把所有的样式固化在了HTML结构上。

设想真实的维护场景,前任开发为了让一个按钮和旁边的输入框对齐,极其随意地写了一个向左偏移负间距的类名:

<Button className='-ml-2 mt-1'>提交</Button>

半年后你接手这个需求,产品要求在这俩元素中间加一个Icon。你看着这个-ml-2mt-1会陷入极其痛苦的挣扎:他当时为什么要写负边距?是因为外层父元素加了错的padding导致的?还是为了抵消Button内部自带的margin?🤷‍♂️

在传统CSS中,我们往往会留有注释说明抵消输入框自带的右侧留白。但在Tailwind里,没有注释的容身之所。

为了保证不出线上Bug,你绝对不敢删掉那个-ml-2。你会选择在它后面再打个补丁,加个pl-4试图把它顶回来。 第二年,另一个接手的同事遇到了错位,又在后面补了一个mt-[-5px]🤣🤣🤣。

日积月累,HTML标签上的类名越来越长,死代码和冲突代码全堆在DOM上,最终变成一座没人敢碰的屎山💩。

别瞎搞,先认清你的场景🫡

说了这么多,难道Tailwind真的就是垃圾吗?当然绝对不是。

如果你在做偏C端的炫酷落地页、做SaaS官网,或者你是独立开发者,没有沉重的历史包袱,不需要配合复杂的重型组件库,那Tailwind绝对是神作。它自带极其优秀的设计规范,能让你极速堆出好看的界面。

但咱们讨论的是中后台。中后台是干嘛的?团队十几个人来回交接,动辄几百个页面,充斥着极其复杂的表单联动和权限校验,生命周期长达五年甚至十年。

在这种重型项目中,保持业务逻辑的纯粹性,分离关注点,远比你少写几行CSS要重要一万倍。

好了,今天分享到这,谢谢大家😁

http://www.jsqmd.com/news/653150/

相关文章:

  • 初次使用降AI工具的完整入门教程:从零开始用嘎嘎降AI达标
  • Android应用如何精准识别并屏蔽主流模拟器运行环境
  • 哔哩下载姬DownKyi:如何免费解锁B站全画质视频下载的终极方案
  • AI客服机器人爆发前夜,你还在用2023版对话引擎?——2026奇点大会6项强制合规新规倒计时47天
  • 下一代软件:告别 GUI,CLI 底层革命
  • 图解 RAG:为什么大模型需要外挂知识库
  • 【JVM深度解析】第01篇:JVM前世今生与技术架构全景
  • 5G NR调度器:从帧结构到资源分配的实战解析
  • Cadence Virtuoso导入TSMC 65nm PDK保姆级避坑指南:从解压到仿真成功全流程
  • 2026 年两款服务器面板内存占用测试:宝塔面板和 1Panel 表现如何
  • GB/T 13123-2026 竹胶合板检测
  • 免费论文AIGC检测使用指南:原理实操全攻略
  • 扫普通链接二维码打开小程序页面参数获取
  • 开发者面试内卷:突出重围的差异化战术
  • 实战解析 | Workbench多单元混合建模在静力学分析中的高效应用
  • 当AI学会害怕和好奇——V4认知与情绪
  • 五大Web GIS地图框架深度对比:Leaflet、OpenLayers、Mapbox、Cesium与ArcGIS for JavaScript
  • 多益网络笔试里的Python哲学题怎么答?‘Explicit is better than implicit’对新手程序员意味着什么?
  • Cursor Pro激活技术深度解析:3大核心技术实现与实战指南
  • 如何用Jasminum插件3分钟搞定中文文献管理:Zotero终极效率提升指南
  • 【JVM深度解析】第02篇:类加载机制深度解析
  • DelphiZXingQRCode 实战:从零到一构建企业级二维码生成模块
  • OpenClaw Windows 一键部署全流程|解压即装+环境免配置,龙虾AI智能体本地快速落地
  • openEuler 22.03下5分钟搞定Docker安装与镜像加速(华为云镜像源实测)
  • 避开Matlab新手必踩的坑:空值判断的正确姿势(为什么a==[]永远返回false)
  • Bring up
  • 家庭网络搭建指南:从光猫到路由器的全流程解析
  • 将小龙虾接入ClawBot教程,用微信就能出电影解说视频
  • vue 拖拽排序实现方案
  • 三堵墙逼出来的智慧——V3障碍与感知