!default 是 SCSS 变量的“首次占坑守门员”,仅在变量未声明时赋默认值;真正换肤依赖 CSS 变量 + var() + JS 动态设置,若漏掉 :root 插值或 JS 设置,换肤即失效。

!default 本身不参与换肤,它只决定 SCSS 变量在编译前“落定成什么值”;真正实现换肤的是 CSS 变量(--primary-color)+ var() + JavaScript 动态设置,!default 的作用是让这套运行时机制有可控的起点。
为什么不能跳过 !default 直接写 $color: #1890ff?
直接赋值会锁死变量,后续所有覆盖尝试都会失败——SCSS 不允许重复定义同名变量。一旦你在组件文件里写了 $primary-color: #1890ff;,外部就再也没法通过任何方式改掉它。
-
$primary-color: #1890ff !default;表示:“如果此前没人声明过这个变量,那就用我这个值” - 项目主题文件(如
_theme-dark.scss)可以安全地写$primary-color: #ff6b6b;(不带!default),只要它在!default声明之后被@import - 若顺序颠倒(比如先
@import "button"再定义变量),button.scss里引用$primary-color就会报错Undefined variable
!default 失效的三个高频现场
它不是“覆盖开关”,而是“首次占坑守门员”。失效往往悄无声息,连警告都没有。
- UI 库已提前定义:查
node_modules/element-plus/scss/_variables.scss,里面可能已有$color-primary: #409eff;,你自己的!default就被跳过 - 构建工具注入了变量:Vite 的
css.preprocessorOptions.sass.additionalData或 Webpack 的modifyVars会在所有文件前插入变量,直接绕过你的!default - 同一文件里先赋值后
!default:$color: red; $color: blue !default;合法但无效——$color已被绑定为red
如何用 !default 构建可维护的主题变量层?
关键不是“怎么写 !default”,而是“谁先看到变量名”。必须把变量声明收口、分层、前置。
立即学习“前端免费学习笔记(深入)”;
- 新建
_variables.scss,只放带!default的语义变量:$color-primary: #1890ff !default;、$border-radius: 4px !default; - 新建
_theme-user.scss(由构建脚本生成或人工维护),只放无!default的强制赋值:$color-primary: #52c418; - 主入口严格按序
@import:@import "_variables.scss"; @import "_theme-user.scss"; @import "components/"; - 组件中禁止重复
@import "_variables.scss"——否则导入顺序混乱,!default逻辑彻底失效
最易被忽略的一点:SCSS 层的变量只是“生成器参数”,最终输出的 CSS 必须依赖 var(--primary-color) 才能换肤。!default 写得再漂亮,如果 :root { --primary-color: #{$primary-color}; } 漏了插值 #{$primary-color},或者 JS 没调用 document.documentElement.style.setProperty('--primary-color', ...),整个换肤链就断在第一环。


















