# 一文看懂 !default 和 !global

315 阅读1分钟

一文看懂 !default 和 !global

在看 element-plus 源码的时候,是不是有很多小伙伴跟我一样对 scss 中的 !default 和 !global 很疑惑?本文将用示例和简单的 js 告诉你 !default 和 !global 的作用。

!default

可以在变量的结尾添加 !default 给一个未通过 !default 声明赋值的变量赋值,此时,如果变量已经被赋值,不会再被重新赋值,但是如果变量还没有被赋值,则会被赋予新的值[1]。

$text-color: red;
$text-color: blue !default;

.block {
  color: $text-color;
}

// 编译后的结果:
// .block {
//   color: red;
// }

用简单的 js 表示如下:

// $text-color: blue !default;
var $text_color = window.$text_color || `blue`;

!global

在早期的 sass 版本中,变量只有全局作用域的,在块中声明的变量会覆盖全局变量:

// sass 3.2 及以下版本
// I instantiated the $text-color variable to Blue
$text-color: blue;

// Here, the intent was to change the color for the .error style
.error {
  $text-color: red;
  color: $text-color;
}

// Following the cascade, in .normal-text, I want Blue, but get Red.
.normal-text {
  color: $text-color;
}

// 编译后的结果:
// .error {
//   color: red;
// }

// .normal-text {
//   color: red;
// }

我们用 js 来表示这种行为:

// 3.2 及以下版本
var $text_color = `blue`;

// .error
{
  $text_color = `red`; // 直接修改全局变量
  $color = $text_color;
}

// .normal_text
{
  $color = $text_color;
}

显然局部变量会作用到全局变量是非常危险的,在 sass 3.2 以上版本开始不再支持局部变量作用到全局变量。例如:

// sass 3.3 及以上版本
$text-color: blue;

.error {
  $text-color: red; // This is now a new local scoped variable
  color: $text-color;
}

.normal-text {
  color: $text-color;
}

// 编译后的结果:
// .error {
//   color: red;
// }

// .normal-text {
//   color: blue;
// }

同样,我们用 js 表示上面的行为:

var $text_color = `blue`;

// .error
{
  var $text_color = `red`; // 重新声明变量
  var $color = $text_color;
}

// normal_text
{
  var $color = $text_color;
}

如果我们想要在块作用域修改全局变量那应该怎么做? 那就需要用到 !global 修饰符。简单来说,

变量支持块级作用域,嵌套规则内定义的变量只能在嵌套规则内使用(局部变量),不在嵌套规则内定义的变量则可在任何地方使用(全局变量)。将局部变量转换为全局变量可以添加 !global 声明[1]。

还是用上面的示例:

// sass 3.3 及以上版本
$text-color: blue;

.error {
  $text-color: red !global;
  color: $text-color;
}

.normal-text {
  color: $text-color;
}

// 编译后的结果
// .error {
//   color: red;
// }

// .normal-text {
//   color: red;
// }

从编译后的结果来看,normal-text 的 color 被修改成 red,说明在 error 使用 !global 修改变量会作用到全局。

接下我们用 js 表示:

var $text_color = `blue`;

// .error
{
  var $text_color = `red`; // !global

  if (window.$text_color != null) {
    window.$text_color = `red`;
  }

  var $color = $text_color;
}

// normal_text
{
  var $color = $text_color;
}

总结

// !default
var $variable = window.$variable || `value`;

// !global
var $variable = `value`;
if (window.$variable != null) {
  window.$variable = $variable;
}

附录

参考文章

[1]: sass 中文文档

[2]: the !default and !global flags