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的主要内容,如果未能解决你的问题,请参考以下文章

Sass 条件语句

Webpack SASS-loader include 语句中断 SASS @import 语句

@import 在子文件夹中的 SASS 文件中不起作用

SASS 是不是支持向 mixin 中的所有属性添加 !important?

Sass的流程控制-----@if语句

Golang入门到项目实战 | golang中的if语句