在Angular 7中设置sass变量值

kun*_*tal 10 javascript sass angular angular6 angular7

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

因为我来自asp.net背景,之前我要做的是在母版页加载,从数据库获取值并将它们写入.less文件,让java脚本库来处理它.这很简单.

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

我刚刚从这里学习了一个新东西APP_INITIALIZER ,但最终这篇文章没有显示如何在.scss文件中写.

我实际上是用我的asp.net知识来思考这个问题,但可能是我错了,或者还有另一种实现方式.

我想要一个简单的解决方案,我们在asp.net中做什么我想以同样的方式实现这一点.

  1. 当应用程序第一次加载时,从数据库通过api获取变量值.

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

  3. 之后SASS将负责这一点,我们得到预期的结果.

请先给出一些建议或示例.

谢谢.

Ven*_*nev 6

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

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

通常,您会为应用程序提供一些基本 css,然后您需要根据管理设置加载其他 css。从css的角度需要考虑的是,附加css中的所有css特异性都应该大于base css,否则不会覆盖base。这需要基本的css知识,所以我不会详细介绍。

方法一

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

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

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

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

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

方法二

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

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

然后将其转换为字符串

cssCode = 'body {background-color: red}';
Run Code Online (Sandbox Code Playgroud)
let additionalCssStyle = document.getElementById('additionalCss');
if (! additionalCssStyle) {
  additionalCssStyle = document.createElement("style");
  additionalCssStyle.id = 'additionalCss';
  document.head.appendChild(additionalCssStyle);
}
additionalCssStyle.innerText = cssCode;
Run Code Online (Sandbox Code Playgroud)
  1. 重新加载 - 将更改保存到后端,然后重复 1. 和 2。


Col*_*rus 5

首先,在 ASP .NET 中,让 db 保存您的样式和其他前端相关资产可能还不错。这是因为它是一个服务器端渲染框架。另一方面,在 Angular 中,它是客户端(Angular Universal 除外,但您仍然必须期望以相同的方式处理它)。即使使用翻译(i18n 或自定义),在 Angular 世界中,它也很可能存储在前端而不是后端(db 左右)。因此,您必须以自己喜欢的某种方式存储“主题”,并使用 Angular 在它们之间动态切换。您当然可以存储样式/主题的键/变量,但它们的实际 CSS 值(类等)应存储在前端。

尝试在动态设置应用主题 (Angular) 时使用 CSS 变量查看这个简单示例。这只是一种方法,有很多方法可以做到这一点,您可能需要寻找您的个人喜好。


Raj*_*pta 5

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

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

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

body[them="theme2"] {
    // theme 2 css
}
Run Code Online (Sandbox Code Playgroud)

您可以将sass 主题地图与条件 css 一起使用。

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

    themeChange() {
    const dom = document.querySelector('body');
    dom.theme = theme1;    // change theme here
    }
Run Code Online (Sandbox Code Playgroud)

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

<some-element [ngStyle]="{'font-style': styleExp}">...</some-element>
Run Code Online (Sandbox Code Playgroud)

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


Hee*_*aaw 2

我不认为你想要做的事情是可能的... 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));
  }
}
Run Code Online (Sandbox Code Playgroud)

希望这有所帮助 :-)