模块化拆分需明确责任边界与依赖关系,组件样式须独立成文件并遵循bem嵌套、参数化mixin、语义化变量及单向core导出规范。

模块化拆分不是为了多建几个文件,而是让每个 .less 文件有明确的“责任边界”和“可预测的依赖关系”。没划清边界的拆分,只会把混乱从一个文件转移到十几个文件里。
组件样式必须单独成文件,但禁止直接写完整规则
每个 UI 组件(如 button、card、toast)对应一个独立的 .less 文件,比如 src/styles/components/button.less。但它里面不能直接写 .btn { ... } 这种裸选择器,也不能硬编码颜色或间距。
正确做法是:
- 开头统一
@import "../core/index";,只引入变量、mixin、函数等基础能力 - 用命名空间包裹:以
.btn为根,所有子类用&__content、&--disabled等方式嵌套生成 BEM 风格类名 - 调用参数化 mixin 构建变体,比如
.button-base()+.button-size(medium)+.button-theme(primary) - 不定义新变量(如
@btn-padding),复用@spacing-md、@radius-sm等语义化变量
core 目录必须单向导出,禁止组件反向 import 变量文件
所有基础能力收口到 src/styles/core/ 下:variables.less、mixins.less、functions.less。它们之间不允许互相 @import(比如 mixins.less 里不能 @import "variables"),全部由 core/index.less 控制加载顺序并一次性导出。
否则容易踩坑:
- 组件文件里写
@import "../core/variables"; @import "../core/mixins";→ 路径一动全报File not found - 两个组件分别
@import同一个 mixin,但传参逻辑不一致 → 编译后生成两份重复 CSS -
variables.less里用了!default,但被mixins.less提前读取 → 主题覆盖失效
Webpack 中配置 lessOptions.paths = ["src/styles"],组件内统一写 @import "core/index"; 即可。
变量命名必须表达用途,而非色值或尺寸
写 @primary-color: #007bff; 是对的;写 @blue-500: #007bff; 或 @header-bg: #f8f9fa; 就埋了雷。
原因很实际:
- 设计系统换主色时,改
@primary-color一处,所有按钮、标签、边框自动同步 -
@header-bg看似合理,但侧边栏、弹窗头、卡片标题可能共用同一层级背景 → 应该用@surface-level-1+@primary-color组合 - 字体大小写
@font-size-lg比@font-20px更安全——响应式场景下它可能被媒体查询动态重置 - 所有变量在
variables.less中声明时加!default,方便上层主题文件覆盖
Mixin 必须正交拆分,禁止单一函数承载全部视觉维度
一个按钮的视觉表现包含尺寸、状态、主题、圆角、阴影等多个正交维度。把它们塞进一个 .btn(@size, @state, @theme, @radius, @shadow) 是自找麻烦。
应该这样组织:
- 尺寸控制高度、内边距、字体大小联动:
.button-size(small)内部查@button-sizesmap - 状态只改交互反馈:
.button-state(hover)用when (@state = hover)guard 判断 - 主题负责颜色体系:
.button-theme(primary)设置@bg、@text、@border等角色变量 - 每个 mixin 只做一件事,且参数带默认值:
.button-size(@size: medium) - 调用链清晰:
.btn { .button-base(); .button-size(medium); .button-state(hover); }
真正难的是变量作用域和 @import 顺序——主题变量必须在任何组件 @import 前生效,否则 mixin 里读到的还是默认值。这点极易被忽略,调试时会发现“明明改了 @primary-color,按钮却没变色”。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











