Sass 中的 @if 语句中的 @import
Posted
技术标签:
【中文标题】Sass 中的 @if 语句中的 @import【英文标题】:@import in @if statement in Sass 【发布时间】:2012-12-02 11:25:22 【问题描述】:我只想加载登录页面所需的 css 以提高性能。在我的其他页面上,我想要一个分组的 css 文件,该文件将缓存在包含我所有 css 的每个页面上。
我有以下文件:
minifiedcssforloginpage.scss
grouped-pages.scss
在 minifiedcssforloginpage.scss 我声明 $load-complete-css:false。之后我导入 myproject.scss ,其中包含我的模块、布局、核心的所有导入......在 myproject.scss 我想做类似的事情
@if $load-complete-css
@import module1;
@import module2;
@import module3;
因此,minifiedcssforloginpage.scss 会生成 minifiedcssforloginpage.css,其 css 少于 grouped-pages.css(将 var $load-complete-css 设置为 true)。
但我得到一个错误,这是不可能的“导入指令可能不能在控制指令或混合中使用”。
【问题讨论】:
不过,您确实明白,SASS 不是动态的,对吧?编译好之后就可以了。没有状态变化或类似的东西。用户登录后,您不能将$loggedin
设置为 true,因为 CSS 已经编译。
是的,这是一个糟糕的命名。我改了
【参考方案1】:
这是不允许的事情之一。您唯一能做的就是将这些导入转换为 mixin(将文件导入到 @if
之外并在适当的地方调用 mixin)。
澄清:
_partial.scss
@mixin partial
.test color: red
// other styles here
styles.scss
@import "partial";
@if $someval == true
@include partial;
【讨论】:
你的意思是像@if $load-complete-css @include othercomponents; @mixin othercomponents @import "module1" ; @import "modules2";
?我现在有同样的错误.. 也不可能在 mixin 中导入
正确:有问题的 mixin 也无法执行导入。如果您想与@if
一起使用,您必须将文件的全部内容放入单个mixin。
一页独有的样式有多少?拆分文件并引发 2 个 HTTP 请求可能比拥有一个包含所有内容的文件更糟糕。
@cimmanon 或者不是。较小的文件可以独立缓存。如果一个或另一个文件将被缓存以供将来的页面加载,则两个 HTTP 请求是没有问题的。我倾向于认为,当前为整个站点连接所有 CSS 和 JS 的时尚是非常糟糕的做法,这是由于未能考虑如何正确模块化造成的。
我对这个解决方案非常感兴趣——非常聪明的想法谢谢!【参考方案2】:
以对您有意义的方式将您的样式放入各种partial 文件中。然后,您可以为您的登录页面创建一个单独的 SASS 文件,该文件只导入具有相关样式的文件。
从my answer引用另一个问题:
目前无法使用 SASS 动态包含文件。
@import
不能在控制指令中使用(例如@if
)或 mixins,在导入指令中使用变量是错误的语法, 并且没有提前结束文件执行的指令(其中 effectively 将允许有条件的导入)。但是,您可以 通过更改样式规则的结构来解决您的问题。...如果您有 [应该] 有条件地包含的样式 [它们] 应该封装在 mixins 中,在“模块”或“库”文件中。 ... 主要思想是导入一个这样的文件不会输出任何 CSS。这样,您可以冗余地导入这些文件,以便您可以使用 任何你需要的 mixin。
【讨论】:
【参考方案3】:核心开发团队不愿实施此功能,尽管他们正在考虑实施全新的依赖系统。
查看以下 Github 问题:
Allow @import within @if (#451) Using @import statements within control directives or mixins (#779) Allow optional @imports (#779) Dynamic Dependencies (#739)【讨论】:
你知道他们为什么不情愿吗?这个功能现在对我非常有帮助。 @thephpdev :您可能想看看@Github 上正在进行的讨论并为讨论做出贡献(请参阅上面的链接)。请求此功能的人越多,他们最终实现它的可能性就越大;-) 是的,我做到了。这就是“最终”的关键。可能不会发生。我看到了他们构建某种新的依赖管理系统的一些事情。但那是三年前的事了。看起来并没有真正发生任何事情。所以我只是没有真正看到这一点。 :) @thephpdev : 他们无法与用户的实际需求联系起来,并且不愿意实现像动态依赖这样重要的功能,这一直困扰着我很长时间,以至于我实际上考虑编写我的自己的预处理器语言......这很糟糕,但我想如果我们想继续使用 Sass,我们只能忍受...... 确实如此。还是喜欢它而不是纯 CSS,虽然哈哈。【参考方案4】:不幸的是,目前没有办法将 import 语句放在 if 块中。
我知道的最接近的替代方法是使用 additionalData
字段向您的 webpack sass-loader
配置添加预处理器函数:
loader: "sass-loader",
options:
sassOptions:
includePaths: [...],
,
additionalData: (content: string, loaderContext)=>
// More info on available properties: https://webpack.js.org/api/loaders
const resourcePath, rootContext = loaderContext;
const finalPath = someCondition ? path1 : path2;
return content.replace(/SomeDynamicPathPlaceholder/g, finalPath);
,
,
,
有关additionalData
字段的更多信息:https://webpack.js.org/loaders/sass-loader/#additionaldata
【讨论】:
【参考方案5】:我知道这是一个非常古老的问题,但我们最近在我们自己的微型 UI 框架中实现了这个,如下所示:
ui-framework/config.scss
$components: (
"component-a": true,
"component-b": false
) !default;
// A bunch of other default config
ui-framework/main.scss
@import "component-a";
@import "component-b";
ui-framework/component-a.scss
@if (map-get($components, "component-a")
.component-a
// Bunch of code here
ui-framework/component-b.scss
@if (map-get($components, "component-b")
.component-b
// Bunch of code here
然后在每个项目中:
a-project/main.scss
// NOTE: We only want component b in this project
$components: (
"component-a": false,
"component-b": true
);
@import "ui-framework/config.scss";
@import "ui-frameowrk/main.scss";
我们不会对每个单独的组件都这样做,但并不总是在使用的大型组件(如幻灯片、对话框、表单相关代码等)。
【讨论】:
【参考方案6】:老问题,我知道;只是觉得我会根据我正在做的事情提供一个替代方案和扩展示例。
我遇到了这个问题,因为我希望将一个 SCSS 文件用于较小的屏幕,而将一个 SCSS 文件用于较大的屏幕(桌面上的顶部菜单导航和移动设备上的汉堡菜单)。
在没有 Bootstrap 的情况下使用 Blazor,我想根据实际 html 使用一个菜单结构,然后使用 SCSS 在相关大小的两者之间切换。我为导航的桌面版本创建了一个 SCSS 文件,并开始为移动版本创建一个。在我意识到这个绊脚石之前,我的计划是根据 mixin 中的媒体查询(恰当地命名为 mobileOrDesktop
)有选择地导入 SCSS。
我的想法是使用这个 mixin 来对媒体大小进行所有基本结构操作。像这样的:
@mixin mobileOrDesktop
@media (min-width: 961px)
@import 'desktopNavbar.scss';
.container-fluid
margin-top: 70px;
height: calc(100% - calc(60px + 70px));
//show the footer, maybe tweak the font size, etc
@media (max-width:960px)
@import 'moblieNavbar.scss';
.container-fluid
height: 100%;
//hide the footer, maybe tweak font sizes, etc
很遗憾,由于 SCSS 的工作原理,我们无法做到这一点。因此,我不只是在媒体查询中转储所有 CSS(我想让它相对分开,以便调试/更改更易于管理),而是寻找替代方案。
与 Cinnamon 类似,我发现最可行的解决方案是在 mixin 之外导入 SCSS,然后将其简单地包含在 mixin 中:
@import 'desktopNavbar.scss';
@import 'mobileNavbar.scss';
@mixin mobileOrDesktop
@media (min-width: 961px)
@include desktopNavbar;
.container-fluid
margin-top: 70px;
height: calc(100% - calc(60px + 70px));
@media (max-width:960px)
@include moblieNavbar;
.container-fluid
height: 100%;
导入的 SCSS 文件本身就是一个 mixin,即 desktopNavbar.scss
变为:
@import 'siteVariables.scss';
@mixin desktopNavbar
#navbar
.burgerIcon
display: none;
.nav
overflow: hidden;
background-color: $navy;
vertical-align: middle;
height: 70px;
line-height: 70px;
color: $blizzard;
position: fixed;
top: 0;
width: 100%;
display: block;
z-index: 99999999;
.leftBlock, .midBlock, .rightBlock
display: inline-block;
vertical-align: middle;
height: 70px;
padding: 0px;
margin: 0px;
line-height: 70px;
.leftBlock
width: 20%;
.imgLogo
margin-left: 10px;
margin-top: 5px;
max-width: 120px;
.midBlock
width: 60%;
text-align: center;
.navbar-nav
display: inline-flex;
flex-wrap: nowrap;
flex-grow: 2;
flex-shrink: 2;
list-style: none;
vertical-align: middle;
margin: 0px;
padding: 0px;
.nav-item
max-width: 175px;
color: $white;
display: inline-block;
vertical-align: middle;
height: 70px;
.btn-link
font-size: 16px;
text-align: right;
color: $white;
padding: 14px;
line-height: 20px;
text-decoration: none;
vertical-align: middle;
span
font-family: 'Font Awesome Solid';
line-height: 60px;
height: 60px;
vertical-align: middle;
padding: 5px;
&.dropdown
font-size: 16px;
text-align: right;
line-height: 20px;
text-decoration: none;
vertical-align: middle;
.dropbtn
font-size: 16px;
text-align: right;
line-height: 20px;
text-decoration: none;
vertical-align: middle;
span
font-family: 'Font Awesome Solid';
line-height: 60px;
height: 60px;
vertical-align: middle;
padding: 5px;
.dropdown-content
display: none;
position: fixed;
top: 68px;
text-align: center;
background-color: $star-command;
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
z-index: 99999999999;
.dropdown-header
color: $blizzard;
.dropdown-item
color: $powder;
padding: 12px 16px;
text-decoration: none;
display: block;
&:hover
background-color: $blizzard;
color: $navy;
&:hover
background-color: $star-command;
.dropdown-content
display: block;
.rightBlock
width: 20%;
站点 SCSS 可以简单地是:
@import '../../FontAwesome/scss/fontawesome.scss';
@import '../../FontAwesome/scss/regular.scss';
@import '../../FontAwesome/scss/solid.scss';
@import 'siteVariables.scss';
@import 'mixins.scss';
//import other stuff here
html, body
height: 100%;
overflow: hidden;
width: 100%;
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif !important;
margin: 0px;
@include mobileOrDesktop;
.container-fluid
overflow: auto;
main
padding: 15px;
#blazor-error-ui
background: lightyellow;
bottom: 0;
box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
display: none;
left: 0;
padding: 0.6rem 1.25rem 0.7rem 1.25rem;
position: fixed;
width: 100%;
z-index: 1000;
.dismiss
cursor: pointer;
position: absolute;
right: 0.75rem;
top: 0.5rem;
【讨论】:
以上是关于Sass 中的 @if 语句中的 @import的主要内容,如果未能解决你的问题,请参考以下文章
Webpack SASS-loader include 语句中断 SASS @import 语句