【问题标题】:Set sass variable value in Angular 7在Angular 7中设置sass变量值
【发布时间】:2019-06-30 17:15:46
【问题描述】:

过去几周我一直在使用 Angular,现在我需要动态设置公共站点的样式。站点管理员在数据库中设置了各种颜色代码以及来自管理员的徽标图像。这些将在公共站点打开时反映出来。

由于我来自 asp.net 背景,以前我要做的是加载母版页,从数据库中获取值并将它们写入 .less 文件,然后让 java-script 库处理它。那里很简单。

但是对于我目前的情况,我使用的是 sass,我无法找到将变量写入 .scss 文件的方法。

我刚刚从here 学到了一个新东西 APP_INITIALIZER,但最终这篇文章没有展示如何在 .scss 文件中写入。

我实际上是根据我的 asp.net 知识考虑的,但可能是我错了,或者有另一种实现方式。

我想要一个简单的解决方案,我们在 asp.net 中所做的我想以同样的方式实现这一目标。

  1. 首次加载应用程序时,通过 api 从 DB 获取变量值。

  2. 在 SASS 变量文件中写入值。

  3. 之后,SASS 会处理这个问题,我们会得到预期的结果。

请给出一些建议或例子,以开始。

谢谢。

【问题讨论】:

    标签: javascript angular sass angular6 angular7


    【解决方案1】:

    首先,在 ASP .NET 中,让 db 保存 CSS 规则和其他静态资产可能还不错。这是因为它是一个服务器端渲染框架,所以有点意思。

    另一方面,在 Angular 中,它是客户端(Angular Universal 除外,但您仍然必须期望使用类似的方法)。即使使用翻译(i18n 或自定义),在 Angular 世界中,它也很可能存储在前端(i18n .json 文件)而不是后端(db 左右)。

    因此,您必须以您喜欢的特定方式存储您的主题,并通过 Angular 在它们之间动态切换。您当然可以存储样式/主题的键/变量,但您的实际 CSS 代码仍存储在 .css 文件中。

    尝试从CSS vars in use while dynamically setting app theme (Angular) 中查看这个简单的示例。这只是一种方法,有很多方法可以做到这一点,您可能需要寻找您的个人喜好。

    更新:

    我上面的回答可能有错误的含义,但我会保持原样,只是分享我与这个主题相关的一个经验。

    我开发了一个 web 应用程序,用户可以通过设置自定义他的主题,同样,CSS 规则不存储在 DB 上,但要在 sass 变量上设置的颜色值是。有一个特殊的脚本将编译 CSS 脚本(按需返回,这让它有点慢,但启动画面只是节省你的时间,而不是 AOT 编译)以及自定义值,我不知道如何它完成了。与翻译相同,我最近也在一个项目中工作,其中翻译来自 db,但是对于每个发布/部署都有一个脚本可以运行,该脚本会生成和更新 assets/i18n 文件夹中的 .json 文件。

    【讨论】:

      【解决方案2】:

      因为 sass 是一个预编译的 css。我们不能在不生成单独的 theme.css 的情况下动态更改主题。这就是 JSS 发挥作用的地方。 JSS 是一种基于 javascript 的样式注入机制,将 css 直接注入到您正在使用的文件中。

      react-angular-material 广泛使用它,我们可以将颜色变量动态传递给应用程序的change theme

      例如,这个人用angular 成功了。

      文档: jss-angular, jss

      链接:jss-with-angular

      【讨论】:

        【解决方案3】:

        虽然@Cold Cerberus 提出了一个很好的方法,并且在前端维护与样式相关的东西是正确的,但我提出了一些方法。

        正如你所说,你想要各种颜色组合,你可以使用 SASS 的条件 CSS。

        body[theme="theme1"] {
           // theme 1 css
        }
        
        body[them="theme2"] {
            // theme 2 css
        }
        

        您可以将sass theme map 与条件 css 一起使用。

        只需更新您的属性,主题就会自动应用。

            themeChange() {
            const dom = document.querySelector('body');
            dom.theme = theme1;    // change theme here
            }
        

        如果您对某些应该从后端更新的元素样式(如颜色代码)非常挑剔,您可以使用 ng-style 和主题方法。

        <some-element [ngStyle]="{'font-style': styleExp}">...</some-element>
        

        您必须使用上述的智能组合才能满足您的要求。

        【讨论】:

          【解决方案4】:

          正如其他答案所解释的,无法在客户端设置 SASS 变量并对其进行处理,因为 SASS 在构建时转换为纯 CSS,并且当应用程序运行时或在 APP_INITIALIZER 浏览器中只能处理 CSS。

          我看到了两个选项来实现你想要的。

          一般情况下,您将拥有一些应用程序的基本 css,然后您需要根据管理员设置加载额外的 css。从 css 的角度需要考虑的是,附加 css 中的所有 css 特异性都应该大于基本 css,因为否则它不会覆盖基本 css。这需要基本的 css 知识,所以我不会详细说明。

          方法一

          根据服务器请求生成额外的 CSS。当应用程序从服务器 URL 启动时加载它。当管理员更改任何设置时,通过 js 重新加载它。

          1. 在地址/additional.css(或者它可能类似于/api/theme/custom-css)定义后端端点,它将从数据库中生成css。例如你在 db 中有background=red,那么端点应该返回
          body {background-color: red;}
          
          1. &lt;head&gt;index.html 中添加&lt;link id="additionalCss" rel="stylesheet" type="text/css" href="additional.css" /&gt;。这足以让它发挥作用。
          2. 要重新加载,您可以使用不同的方法,但我相信这应该可行
          document.getElementById('additionalCss').href = document.getElementById('additionalCss').href;
          

          这将向服务器发出新请求,服务器将执行 DB -> css 并返回更新后的 css,该 css 将应用于浏览器。

          如果你想酷(或者需要支持大而复杂的主题)可以使用scss。后端应该从数据库中生成 scss 变量定义,然后应该使用一些服务器端应用程序编译 scss -> css,然后将编译后的 css 提供给客户端。但是如果额外的 css 足够简单,这将是矫枉过正。

          这种方法的一个重要考虑是浏览器缓存,因为additional.css后面的内容是动态的,但是浏览器可能会缓存它,而不是调用后端并提供过时的版本。

          方法二

          如果您不想或不能弄乱后端。通过json中的某个API端点从DB加载设置,然后在客户端生成css代码并应用它。

          1. 使用 HttpClient 获取设置 JSON 并从中生成 css 作为字符串。例如服务器返回
          {
            "background": "red"
          }
          

          然后将其转换为字符串

          cssCode = 'body {background-color: red}';
          
          1. 使用
          let additionalCssStyle = document.getElementById('additionalCss');
          if (! additionalCssStyle) {
            additionalCssStyle = document.createElement("style");
            additionalCssStyle.id = 'additionalCss';
            document.head.appendChild(additionalCssStyle);
          }
          additionalCssStyle.innerText = cssCode;
          
          1. 要重新加载 - 保存更改为后端,然后重复 1. 和 2.

          【讨论】:

            【解决方案5】:

            这种方式是不可能的,但不是使用 sass 变量,而是使用 sass 变量的值。它可以是任何值。

            为什么?因为sass是在打包的时候编译的,到最后还是会生成平面CSS。

            使用此可选样式处理器的框架示例是 angular。


            在您的情况下,我建议您研究 Angular 中的动态主题,因为您需要的内容肯定需要 JavaScript。查看其中一位贡献者提供的关于媒体的指南。

            https://stackoverflow.com/a/54559350/3070499

            【讨论】:

              【解决方案6】:

              我不认为您想要做的事情......Angular 在应用程序构建期间处理 SASS 文件并将所有常见结果写入一个普通的旧 css 文件。特定于组件的内容将生成为 javascript,进而在运行时应用您的样式。

              因此,您需要设置的所有 SASS 变量都必须在编译时存在。

              不过,您可以做的是在 Angular 组件中预先定义您的设置,然后根据输入(来自您的数据库或其他任何地方)进行切换,如下所示:

              // your.component.ts
              @Component({
                // ... component stuff
                styles: ['h1.option1 {color: red;}', 'h1.option2 {color: blue;}'],
                template: `
                  <h1 *ngIf="optionSelection$ | async as option; else noOption"
                      [class.option1]="option == 1" 
                      [class.option2]="option == 2">
                     Hey there, I'm styled!
                  </h1>
                  <ng-template #noOption>
                    <h1>No option received</h1>
                  </ng-template>
                `
              })
              export class YourComponent {
                optionSelection$: Observable<number>;
                constructor(yourService: YourService){
                  this.optionSelection$ = yourService.getYourOption().pipe(startWith(null));
                }
              }
              

              希望这会有所帮助:-)

              【讨论】:

                猜你喜欢
                • 2011-12-29
                • 2012-04-18
                • 2014-12-09
                • 2011-08-01
                • 2013-06-13
                • 2019-05-04
                • 2013-08-09
                • 2019-05-10
                • 1970-01-01
                相关资源
                最近更新 更多