在Angular 7中设置Sass变量值

12

我最近几周一直在使用Angular,现在我有一个要求需要动态地样式化公共网站。网站管理员在数据库中设置了各种颜色代码以及Logo图像。当公共网站打开时,这些将被反映出来。

由于我来自asp.net背景,以前我会在母版页面加载时,从数据库中取值并将其写入.less文件,然后让JavaScript库处理它。那很简单。

但对于我的当前情况,我正在使用Sass,而我无法找到一种将变量写入.scss文件的方法。

我刚学了一个新东西——应用程序初始化器,但最终这篇文章没有展示如何在.scss文件中进行写入。

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

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

  1. 在应用程序首次加载时通过API从数据库中获取变量值。

  2. 将值写入Sass变量文件中。

  3. 之后Sass将负责处理这些值,我们将得到预期的结果。

请您给出一些建议或示例,让我可以开始尝试。

谢谢。

6个回答

6
首先,在ASP .NET中,可以将CSS规则和其他静态资源保存在数据库中,这是因为它是一个服务器端渲染框架,所以这样做有点意义。
另一方面,在Angular中,它是客户端渲染(除了Angular Universal之外,但您仍然需要期望采用类似的方法工作)。即使使用翻译(i18n或自定义),在Angular世界中,最可能存储在前端(i18n .json文件)而不是后端(数据库或其他)。
因此,您需要以您喜欢的特定方式存储您的主题,并通过Angular动态地在它们之间切换。当然,您可以存储样式/主题的键/变量,但实际的CSS代码仍存储在.css文件中。
尝试查看CSS vars in use while dynamically setting app theme (Angular)的简单示例。这只是一种方法,有很多方法可以做到这一点,您可能需要寻找个人喜好。
更新:

我上面的回答可能存在一些错误的暗示,但是我会保留它,并分享我与这个主题相关的经历。

我曾经在一个Web应用程序上工作,用户可以通过设置自定义他们的主题。同样,CSS规则不存储在DB中,而是存储在要设置为sass变量的颜色值中。有一个特殊的脚本,用于编译CSS脚本(按需返回,这使得它有点慢,但是闪屏可以节省你的时间,没有AOT编译),以及定制值,我不知道如何完成。翻译也是一样,最近我也参与了一个项目,其中翻译来自数据库,但是每次发布/部署都有一个脚本运行,生成并更新assets/i18n文件夹中的.json文件。


6

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

我看到实现您想要的有两个选项。

通常,您会有一些应用程序的基本css,然后根据管理员设置需要加载附加的css。从css的角度来考虑,所有附加的css中的css特异性都应该大于基本css,否则它将无法覆盖基本css。这需要基本的css知识,因此我不会详细说明。

方法1

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

  1. 在地址/additional.css(或类似于/api/theme/custom-css)定义后端端点,它将从数据库中生成css。例如,您的数据库中有background=red,则端点应返回
body {background-color: red;}
  1. index.html<head>中添加<link id="additionalCss" rel="stylesheet" type="text/css" href="additional.css" />,这样就足以使其起作用。
  2. 重新加载页面有许多方法,但我认为这个应该可行。
document.getElementById('additionalCss').href = document.getElementById('additionalCss').href;

这将向服务器发出新请求,服务器将执行DB -> css并返回更新后的css,然后应用于浏览器。
如果你想要酷炫一些(或需要支持大型和复杂的主题),可以使用scss。后端应该将数据库中的scss变量定义生成为后端应用程序来编译 scss -> css,然后将编译后的css返回给客户端。但如果附加的css足够简单,则这将是不必要的。
这种方法的一个重要考虑因素是浏览器缓存,因为additional.css后面的内容是动态的,但浏览器可能会将其缓存,而不调用后端并提供过时的版本。
方法2:
如果您不想或无法干扰后端,请通过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和2。

6

虽然@Cold Cerberus提出了一个不错的方法,并且在前端维护样式相关的事情上是正确的,但我提出了一些方法。

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

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

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

你可以使用sass主题映射与条件css一起使用。
只需更新你的属性,主题就会自动应用。
    themeChange() {
    const dom = document.querySelector('body');
    dom.theme = theme1;    // change theme here
    }

如果您非常关注某些应从后端更新的元素样式(如颜色代码),则可以使用ng-style与主题方法结合使用。
<some-element [ngStyle]="{'font-style': styleExp}">...</some-element>

你需要巧妙地组合上述内容以满足你的需求。

2
我觉得你想要的可能无法实现...Angular在应用程序构建过程中处理SASS文件,并将所有公共结果写入普通的css文件。组件特定的内容将生成为javascript,然后在运行时应用您的样式。
因此,您需要在编译时设置所有必需的SASS变量。
但是,您可以在Angular组件中预定义设置,然后基于输入(来自DB或其他地方)切换它,如下所示:
// 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));
  }
}

希望这能帮到您一点:最初的回答。 :-)

1

由于Sass是预编译的CSS,我们无法动态更改主题而不生成单独的theme.css文件。这就是JSS发挥作用的地方。 JSS是一种基于JavaScript的样式注入机制,可以将CSS直接注入到正在使用它的文件中。

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

例如,这个人用angular做了这个。

文档:jss-angular, jss

链接:jss-with-angular


0

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

为什么?因为sass在打包期间编译,在最终阶段,它仍然会生成普通的CSS。

一个使用这种可选样式处理器的框架的例子是Angular。


在您的情况下,我建议您研究一下Angular中的动态主题,因为您所需的肯定需要JavaScript。请查看贡献者提供的Medium指南。

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接