导入
约 1534 字大约 5 分钟
2025-04-27
Stylus 提供了@import
和 @require
两种方式来导入其他样式表,其功能比原生 CSS 的 @import
更强大且灵活。以下是详细解析:
一、简介
注意:在所有使用 @import
导入 Stylus 样式表的场景中,都可以用 @require
替代,文末会有二者的对比。
1、文件扩展名处理
当我们使用@import
导入样式文件时,如果没有指定文件扩展名为.css
,则 Stylus 会默认将其视为 .styl
文件。
以下是 Stylus 对 两种文件的处理方式:
.styl
文件:Stylus 会动态解析并合并.styl
文件的内容。@import "reset.css";
.css
文件:Stylus 不会编译或合并.css
文件的内容,而是直接输出为 CSS 原生的 @import 语句。// 直接输出 CSS 原生 @import 语句 @import "reset.css"
2、路径查找机制
默认路径:以当前 Stylus 文件所在目录为基准(由
filename
选项定义)。自定义路径:通过
paths
配置项扩展搜索目录,例如:stylus(css).set("paths", [__dirname, "./src/styles", "./vendor"]); // 编译配置
// 优先在当前目录下查找 colors.styl // 其次搜索 ./src/styles/colors.styl // 最后搜索 ./vendor/colors.styl @import "colors"
@import
的工作机制是通过遍历目录数组 paths
,检查目标文件是否存在于这些目录中(类似于 Node.js 的 require.paths
)。该数组默认包含当前文件所在的目录。
例如:如果当前文件名是 /tmp/testing/stylus/main.styl
,则导入操作将优先在 /tmp/testing/stylus/
目录下查找,如果查找不到再去配置的其他目录查找。
3、配置 paths
文件查找目录
通过 paths
选项可以配置 Stylus 查找文件的路径。
使用 Stylus JavaScript API 配置
在下面的示例中,我们通过设置
paths
选项为 Stylus 提供额外路径。在./test.styl
文件中,既可以@import "mixins/border-radius"
,也可以直接@import "border-radius"
(因为./mixins
目录已对 Stylus 暴露)。/** * Module dependencies. */ var stylus = require("../"); var str = require("fs").readFileSync(__dirname + "/test.styl", "utf8"); var paths = [__dirname, __dirname + "/mixins"]; stylus(str) .set("filename", __dirname + "/test.styl") .set("paths", paths) .render(function (err, css) { if (err) throw err; console.log(css); });
在 webpack 中配置
在 webpack 中配置 Stylus 时,可以通过
stylusOptions
选项来设置paths
。// webpack.config.js 或 vue.config.js module.exports = { module: { rules: [ { test: /\\.styl$/, use: [ { loader: "stylus-loader", options: { stylusOptions: { paths: [ path.resolve(__dirname, "src/components/common/"), // 公共样式目录 path.resolve(__dirname, "../"), // 项目根目录 ], }, }, }, ], }, ], }, };
二、高级特性
1、块级导入(嵌套导入)
Stylus 支持块级导入,这意味着 @import
不仅可以在根层级使用,还能嵌套在其他选择器或其他 @rule
内部。
假设你有一个 bar.styl
文件,代码如下:
.bar
width: 10px;
我们可以在 foo.styl
文件中导入 bar.styl
,代码如下:
.foo
@import 'bar.styl'
@media screen and (min-width: 640px)
@import 'bar.styl'
然后你得到的编译结果为:
.foo .bar {
width: 10px;
}
@media screen and (min-width: 640px) {
.bar {
width: 10px;
}
}
2、使用文件通配符导入
Stylus 支持文件通配符(globbing)功能,通过该功能可以使用文件通配符一次性导入多个文件:
@import 'product/*'
该指令将会导入 product
目录下的所有 Stylus 样式表,其目录结构如下所示:
product
body.styl
foot.styl
head.styl
请注意该功能同样适用于 @require
,当存在 ./product/index.styl
文件且包含以下内容时:
@require 'head'
@require 'body'
@require 'foot'
此时 @require 'product/*'
将只会包含每个独立样式表仅一次。
3、相对路径解析
默认情况下,Stylus 不会自动解析被导入 .styl
文件中的相对路径。
例如我们有以下目录结构: ::: file-tree
- foo
- foo.styl
- bar - bar.styl - baz.png
::: 其中 bar.styl
中包含以下内容:
div
background: url("baz.png")
我们在 foo.styl
中使用相对路径引入bar/styl
:
@import "bar/bar.styl"
那么编译后的 CSS 中 url("baz.png")
不会被解析为 url("bar/baz.png")
。 如果我们想让 url("baz.png")
被解析为 url("bar/baz.png")
,我们可以使用 --resolve-url
(或简写 -r
)CLI 选项:
4、索引文件模式查找
@import
支持索引文件模式。
例如:代码中有这样一个导入 @import blueprint
代码,Stylus 会解析为 blueprint.styl
或 blueprint/index.styl
。
这个特性对于需要暴露全部功能同时允许按需导入子模块的库非常有用。
以下是一个典型的库目录结构示例:
tablet
index.styl
vendor.styl
buttons.styl
images.styl
5、条件导入(动态逻辑)
可结合 Stylus 的条件语句按需导入文件:
if env == "development"
@import "debug-tools" // 开发环境加载调试工具
6、媒体查询与原生 CSS 混合
导入 CSS 文件时支持媒体查询参数:
@import "print.css" screen and (min-width: 768px) // 输出带条件的 @import
三、@import
vs @require
除 @import
外,Stylus 还提供了 @require
指令。两者的功能和工作方式基本一致,但是有以下区别:
1、文件类型兼容性
@import
:支持.css
和.styl
文件,默认情况下会将.css
文件视为原生 CSS 导入。@require
:仅支持.styl
文件,不支持.css
文件。
2、重复导入处理
@import
:同一个文件可以多次被导入,可能导致代码冗余。@require
:会检查重复导入,确保模块仅被导入一次,避免重复加载。
3、文件没找到
@import
:如果文件不存在,不会抛出错误,而是继续执行。@require
:如果文件不存在,会抛出错误。
4、处理时机
@import
:在编译时处理,会将所有导入的文件合并到一个文件中。@require
:在运行时处理,会在每个导入的文件中查找并执行。
四、使用建议
1、重复导入风险
Stylus 默认不会检查重复导入,可能导致代码冗余:
// 多次引入同一文件
@import "variables/colors"
@import "variables/colors" // 编译后变量会被重复定义
2、路径冲突规避
避免同名 .css
和 .styl
文件共存:
@import "button" // 若存在 button.css 和 button.styl,可能意外引入 CSS 文件
3、性能优化建议
高频复用模块(如变量库)建议改用
@require
(自动单次加载)。大型项目推荐拆分模块,使用索引文件(
index.styl
)对外暴露模块,同时在文件内导入所有的依赖。
更新日志
e7112
-1于