A. SCSS 完整自学中文版文档教程10_Sass的模块化【Sass/SCSS 官方英文文档翻译整理】
Sass的模块化详解
Sass的模块化主要通过@use指令来实现。@use加载的样式表被称为模块(moles),Sass提供了许多内置模块,包含有用的功能。
@use加载的模块在编译后只会输出一次到css中,而使用@import多次引入同一模块会反复输出到css中。编译后的css结果展示了这一点。
@use前面只能出现@forward或变量声明,所有代码只能出现在@use之后。加载模块成员时,可以通过.、.()、@include .()来访问。
使用@use加载的模块成员只能在当前文件中访问,若希望多文件共同访问,可使用@forward规则通过一个共享文件转发所有成员。@use将命名空间添加到成员名中,因此编写简单名称如$radius或$width是安全的,这与旧的@import规则不同,后者鼓励用户编写像$mat-corner-radius这样的长名称以避免与其他库冲突,@use有助于保持样式表的清晰和可读性!
使用@use ... as ...语法可以来自定义命名空间名称,@use ... as *语法则去除命名空间,但不建议这样做,以免导致命名冲突。
私有成员可通过在模块成员前使用-或_来隐藏,使其不暴露给其他文件访问。
配置引入时,如果模块中的变量使用了!default标志并有默认值,可在使用@use引入时配置自己的值来覆盖默认值。
用@use ... with ...配置模块非常方便,特别是在使用最初为使用@import规则而编写的库时,但不推荐用于更高级用例。若需一次配置很多变量,可通过传递一个map作为配置,或在模块加载后更新配置,考虑写一个mixin来设置变量,再写另一个mixin来注入样式。
使用@use "mole"引入模块时,无需写扩展名,程序会自动查找。在所有系统上,路径分隔符统一使用/而不是反斜线\。当前目录模块不需要写./。文件名以_开头的Sass文件只打算作为模块加载,而不是自己编译,这些被称为部分(partials),它们告诉Sass工具不要尝试自己编译这些文件。导入这些模块时可以不用书写_符号。
使用@use "directory"导入一个目录时,编译器会尝试自动查找_index.scss或_index.sass文件。加载一个纯CSS文件作为模块时,不允许任何特殊的Sass特性(如variables, functions, mixins),为了避免作者一不小心把Sass写进CSS中,所有Sass特性如果不是合法的CSS代码将会报错。否则,CSS将按原样呈现,甚至可以被继承(extend)!
当使用@use加载一个文件时,这个文件可以使用@forward来使另一个文件中的mixin、函数和变量可以暴露出去,通常用于跨多个文件组织Sass库。@forward和@use使用方式相同,但作用却完全不一样。@forward的作用是转发模块成员,而不是引入成员到当前文件使用。加载一个模块的成员通过@forward后,这些成员并不能在当前文件内访问,而仅仅是将这些成员当作自己的成员对外暴露出去。例如,在a.scss中定义了变量$red,在b.scss中使用@forward "a.scss",但在b中无法访问a.$red,但在另一个文件c.scss中使用@use "b.scss"后,可以通过b.$red访问到a中定义的变量。如果想要在b.scss中使用变量,依然需要使用@use "a.scss"来引入变量,然后就可以访问a.$red了。在b.scss文件中同时使用@forward和@use时,建议先写@forward再写@use,因为这样,在c.scss中使用@use...with()配置的变量值会先生效,这样b.scss引用的变量也是配置后的变量。@forward虽然对变量、mixin、函数等只能起转发作用,但对其他样式代码和@use一样,也会引入并编译,所以在使用了@forward"mole"的文件中,就算没有使用@use,也可以去继承mole.scss的样式。
当一个文件转发多个文件中的成员时,在使用时可能会存在多个文件中的成员同名,这样会导致编译出现错误,就算没有同名,也有可能在使用时不清楚到底是哪个模块的成员。通过@forward "mole" as xxx-*可以给同一个模块中的成员统一添加前缀。
默认情况下,@forward会将一个模块中所有成员都转发,如果只想转发某些成员,或不想转发某些成员,可以这样书写,各个成员通过逗号,分隔开,如果成员是变量,不能省略$符号。在转发其他模块的成员时,可以对成员进行配置,修改默认值,或者指定一个确定的值均可。
在 sass 中导入 css 文件时,不要显示地写出扩展名.css,只写文件名即可。因为如果显示地写出扩展名.css,这用来表示是在导入纯 css 文件,编译器则不会去编译@import语句,而是原封不动地输出这条语句。如果将@import"a;"改为@import"a.css;",上面代码编译时会报错:目标选择器未找到,因为编译器遇到@import"a.css";语句,它就会认为这是一条导入纯 css 文件的语句,不需要在编译阶段处理它,而是用于运行时的导入。所以要去继承这个文件中的选择器是无法找到目标选择器的。
在 sass 中导入 css 并编译时,导入的 css 代码块将嵌套在该上下文中,这使得嵌套的@import对于将 CSS 块定位到特定元素或媒体查询非常有用。在嵌套@import 引入的文件中定义的顶级 mixins,函数,变量依然会被导入为全局的变量。在 sass 中导入 css 文件时,不要显示地写出扩展名.css,只写文件名即可。如果显示地写出扩展名.css,这用来表示是在导入纯 css 文件,编译器则不会去编译@import语句,而是原封不动地输出这条语句。如果将@import"a;"改为@import"a.css;",上面代码编译时会报错:目标选择器未找到,因为编译器遇到@import"a.css";语句,它就会认为这是一条导入纯 css 文件的语句,不需要在编译阶段处理它,而是用于运行时的导入。所以要去继承这个文件中的选择器是无法找到目标选择器的。
假设在index.scss中@import"b.scss",而b.scss中使用了@use"a.scss",在index.scss中可以访问b.scss中的所有成员(包括私有成员),但无法直接访问a.scss中的成员,除非b.scss中使用了@forward"a.scss"。
假设我们在维护一个sass库,如果我们改成新的模块系统(@use),我们会担心那些之前使用@import的用户会无法正常运行。为了解决这个问题,sass支持一种文件叫做“@import专用文件”,也就是这个文件只能通过@import导入,而无法通过@use来导入。给一个文件命名为.import.scss即可,这样就能保持对@import的兼容,又能使用新的@use模块系统。
使用@use导入模块,如果模块中使用了@import导入其他文件,index.scss无法访问到a.scss中没有被转发的成员,但是a.scss中的所有样式代码依然会被全部导入。
在sass中导入css文件时,不要显示地写出扩展名.css,只写文件名即可。因为如果显示地写出扩展名.css,这用来表示是在导入纯css文件,编译器则不会去编译@import语句,而是原封不动地输出这条语句。如果将@import"a;"改为@import"a.css;",上面代码编译时会报错:目标选择器未找到,因为编译器遇到@import"a.css";语句,它就会认为这是一条导入纯css文件的语句,不需要在编译阶段处理它,而是用于运行时的导入。所以要去继承这个文件中的选择器是无法找到目标选择器的。
假设在index.scss中@import"b.scss",而b.scss中使用了@use"a.scss",在index.scss中可以访问b.scss中的所有成员(包括私有成员),但无法直接访问a.scss中的成员,除非b.scss中使用了@forward"a.scss"。
假设我们在维护一个sass库,如果我们改成新的模块系统(@use),我们会担心那些之前使用@import的用户会无法正常运行。为了解决这个问题,sass支持一种文件叫做“@import专用文件”,也就是这个文件只能通过@import导入,而无法通过@use来导入。给一个文件命名为.import.scss即可,这样就能保持对@import的兼容,又能使用新的@use模块系统。
使用@use导入模块时,在模块被第一次@import的语句前面,定义一个全局变量即可配置变量值而不使用默认值。模块只会被加载一次,所以就算在第一次@import模块后更改了配置(即使是间接的),再次@import模块也不会使用修改的配置。如果通过@use或@forward去加载一个使用了@import的文件,将会加载到这个文件的所有公共成员及样式,以及它@import导入的所有成员和代码,相当于就是@import导入的文件的内容就像是直接写在@import语句的位置一样。