一个 4700 行小程序里,为什么样式代码比逻辑代码还多

举报
哦啦啦啦啦 发表于 2026/09/30 17:33:08 2026/09/30
【摘要】 先看数字:样式是逻辑的 2.1 倍用 wc -l 数一遍这个小程序(47 个文件、4355 行):类型行数占比.js(逻辑)1,11225.5%.wxss(样式)2,36554.3%.wxml(模板)79818.3%样式 ≈ 逻辑的 2.1 倍。"样式比逻辑多"不是错觉。这在小程序项目里常见,但为什么常见?这次不是泛泛而谈"UI 复杂",而是能数出四个具体成因。成因一:没有 CSS 变量,主...

先看数字:样式是逻辑的 2.1 倍

用 wc -l 数一遍这个小程序(47 个文件、4355 行):

类型 行数 占比
.js(逻辑) 1,112 25.5%
.wxss(样式) 2,365 54.3%
.wxml(模板) 798 18.3%

样式 ≈ 逻辑的 2.1 倍。"样式比逻辑多"不是错觉。这在小程序项目里常见,但为什么常见?这次不是泛泛而谈"UI 复杂",而是能数出四个具体成因。

成因一:没有 CSS 变量,主色手写约 30 次

app.wxss 顶部有一段很诚实的注释:

/* ===== 颜色变量(WXSS 不支持变量,这里仅做注释参考)
   主色 #4A6CF7  成功 #00C853  警告 #FFB300  危险 #FF3D00  信息 #00B8D4
   页面背景 #F5F6FA  卡片 #FFFFFF  正文 #1F2937  次要文字 #6B7280  边框 #E5E7EB
===== */

作者把设计色板记成了注释,然后……全项目真的没有变量。主色 rgba(74, 108, 247, …) 散落在 11 个文件里约 30 次。这不是作者偷懒——WXSS 原生确实不支持 var(),想用变量得上 Sass/Less 预处理,而项目没引入预处理(这是刻意保持零构建的取舍)。

结果就是:改一次主题色 = 手动改 30 处。设计 token 只能靠注释约定 + 眼睛自检,这是样式膨胀的第一桶金——每条规则都要写全色值,规则自然变长、变多。

成因二:整块代码跨页复制

看两个页面:pages/ssh-keys/index.wxss 和 pages/servers/index.wxss,右上角的浮动加号按钮(FAB)样式几乎逐字节重复:

.fab-plus::before {
  content: '';
  position: absolute;
  width: 40rpx;
  height: 6rpx;
  background-color: #FFFFFF;
  border-radius: 3rpx;
  top: 17rpx;
  left: 0;
}

.fab-add + .fab-plus::before/::after(用伪元素画加号)这 8 行规则,在两个页面各写了一份。类似的还有 .modal-input / .form-input / .msg-input、.tag、.cell-group、.empty-state 在组件和页面里反复定义。

为什么没人抽到公共区?因为两个原因叠加:小程序组件默认样式隔离(组件的样式不影响外部、外部也改不动组件内部),组件要带自己的样式副本;而页面之间的公共样式虽然可以放 app.wxss,但项目没有用 @import(其实可抽而未抽)。于是"复制粘贴"成了最省事的复用方式——这正是样式文件膨胀的最大来源。

成因三:约 200 行 CSS 手绘图标

项目里几乎没有图片资源,图标全靠 CSS 画:profile 页 6 个图标(服务器/密钥/AI/帮助/盾牌/信息)、tab-bar 2 个图标(对话气泡/人形)、空状态图(钥匙/服务器)、加号。总量约 200 行,全部用 position: absolute + border + border-radius 手绘。

比如对话气泡图标:

.icon-chat--active .chat-bubble-1 { /* 子元素颜色随父类切换 */ }

这 200 行的"样式即素材"是双刃剑:省掉了图片文件、天然适配 rpx 缩放、不依赖网络资源;但每画一个图标就是 20-40 行 CSS,视觉复杂度直接换算成样式体量。在零图片资源的约束下,样式文件被迫承担了"素材"的职责——这也是它比逻辑多的结构性原因。

成因四:组件样式隔离的隐性成本

3 个组件的 json 都没声明 styleIsolation,走小程序默认的 isolated——组件样式与外部完全隔离。这带来一个发现:server-card/index.wxss 里敢定义与 app.wxss 同名的 .tag / .tag-blue 而不冲突。

隔离是好事(不怕污染),但也有代价:app.wxss 的公共工具类在组件里用不上(隔离模式下组件不继承全局样式,除非用 options: { styleIsolation: 'shared' }),每个组件都必须自带一份"看起来一样"的样式。公共样式体系在页面层成立、在组件层失效,复用链条断了一截。

工程化亮点:值得留下的两套约定

说完问题,也要盘点作者做得对的部分:

1. app.wxss 工具类体系确实在跨页面复用:

.flex-between { display: flex; align-items: center; justify-content: space-between; }
.text-ellipsis { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mt-16 { margin-top: 16rpx; }
.p-16 { padding: 16rpx; }

wxml 里大量引用 <text class="nav-server-text text-ellipsis">——工具类 + BEM 语义类混用,这是"半工程化"最重要的一根柱子。

2. 全项目统一 BEM 命名 + hover-class 约定: 类名都是 块-元素--修饰符(.key-main--hover、.picker-item--active、.modal-input--error),配 --hover 后缀表示按压态(WXSS 下小程序没有 :hover,统一用 hover-class 代替)。命名约定是零成本、生效范围最大的工程化——它让 11 个文件的类名风格一致,新加样式时"照着写"就行。

还有两个 WXSS 的特性值得点赞:全项目用 rpx 响应式单位(750rpx 设计稿基准);3 处 env(safe-area-inset-bottom) 安全区适配(tabBar 和输入栏的 padding-bottom: calc(16rpx + env(safe-area-inset-bottom))),这两点都是"小程序正确姿势"。

总结:半工程化是合理的中间态

这个项目样式膨胀的根源不是"写的人不讲究",而是约束与需求的错配:想零构建 → 没有预处理器 → 没有变量;想零图片 → CSS 手绘图标 → 样式当素材;组件隔离 + 不用 @import → 复制粘贴是最优解。

但作者仍然守住了两条硬约定(工具类 + BEM/hover-class),让 2365 行乱而不散。如果未来要重构,优先级其实很清楚:先引预处理解决变量和 @import 复用,再把跨页重复的 FAB/弹窗抽成公共组件——这两步做完,样式行数能砍掉三成。但在此之前,这个"半工程化"状态对一个小而活的 demo 是完全够用的。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。