我想根据Angular自举之前已知的变量动态地应用SCSS样式。是否可以通过编程方式更改styles.scss
?在启动前的main.ts
中,我想动态添加一行:
@import 'assets/styles/customerA/_themes.scss';
or
@import 'assets/styles/customerB/_themes.scss';
取决于来自服务器的变量值。
如果以上操作不可行,是否有任何方法可以用将在服务器上定义的另一个文件的内容填充styles.scss
?我想更改styles.scss
,而不要更改任何其他“本地” scss文件。
答案 0 :(得分:5)
我建议遵循Angular Material网站的一般形式:https://github.com/angular/material.angular.io/blob/master/angular.json。值得克隆此仓库并在本地使用它。有几个运动部件。
在angular.json文件中,您将如下添加css。注意,您需要将scss分别编译为css才能起作用。他们在tools/build-theme.sh
脚本中执行此操作。 :
{
"input": "src/assets/customer-1-theme.css",
"lazy": true,
"bundleName": "customer-1-theme"
},
{
"input": "src/assets/customer-2-theme.css",
"lazy": true,
"bundleName": "customer-2-theme"
},
然后,查看其样式管理器:https://github.com/angular/material.angular.io/blob/master/src/app/shared/style-manager/style-manager.ts
您将创建一个函数,根据需要动态添加和删除此样式表:
function createLinkElementWithKey(key: string) {
const linkEl = document.createElement('link');
linkEl.setAttribute('rel', 'stylesheet');
linkEl.classList.add(getClassNameForKey(key));
document.head.appendChild(linkEl);
return linkEl;
}
然后在ThemePicker中设置一个可观察的对象来管理主题的设置和删除。参见(https://github.com/angular/material.angular.io/blob/master/src/app/shared/theme-picker/theme-picker.ts):
installTheme(themeName: string) {
const theme = this.themes.find(currentTheme => currentTheme.name === themeName);
if (!theme) {
return;
}
this.currentTheme = theme;
if (theme.isDefault) {
this.styleManager.removeStyle('theme');
} else {
this.styleManager.setStyle('theme', `assets/${theme.name}.css`);
}
if (this.currentTheme) {
this._themeStorage.storeTheme(this.currentTheme);
}
}
就个人而言,我的处理方式略有不同,但这意味着scss会编译到一个css文件中,并且该类是动态选择的。他们的方法增加了一个额外的构建步骤,但允许延迟加载已编译的scss。
管理全局样式
您会在他们的angular.json文件中注意到,他们有一个main.scss,无论选择哪种辅助样式都可以使用它。该文件将处理您需要的所有全局主题。请注意,他们在main.scss中导入了多个Sass partials
。这些允许他们为任何主题设置全局样式。您可以研究它们的用法,在这里使用它们的主要原因是它们可以通过使用mixins将变量从次要sass文件传递到这些parts。
@mixin material-docs-app-theme($theme) {
$primary: map-get($theme, primary);
.docs-primary-header {
background: mat-color($primary);
map-get
是Sass函数,它使您能够定义对象并在Mixins中使用其值。材质设计在这里使用的是sass函数,但是您可以使用更简单的方法在main.scss中获取自定义颜色。在您的style-a / style-b scss中创建一个自定义主题。
$my-custom-theme: (
background-color: #ffff,
button-background: rgba(200, 200, 200, 0.6),
foreground: #34383c
);
然后,将其@include更改为:
@include material-docs-app-theme($theme, $my-custom-theme);
material-docs-app-theme主题混合将更改为:
@mixin material-docs-app-theme($theme, $my-custom-theme) {
$background-color: map-get($my-custom-theme, background-color);
.our-background {
background-color: $background-color;
}
这使您有机会在各个延迟加载的样式表中定义自定义颜色,并使它们在全局main.scss中可用。来自Sass的Mixins和Partials使之成为可能。
答案 1 :(得分:2)
经过很多努力后,我在CSS variables
中找到了答案。那正是我想要的!您可以在运行时更改它们,因此可以执行 动态主题 。这是一篇很好的文章,描述了Angular中的步骤:
https://medium.com/@amcdnl/theming-angular-with-css-variables-3c78a5b20b24
答案 2 :(得分:1)
ngOnInit() {
// Do some stuff to figure out which css url you want
this.cssUrl = '/assets/styles1.css';
}
在您的html文件中
<link rel="stylesheet" [href]='sanitizer.bypassSecurityTrustResourceUrl(cssUrl)'>
答案 3 :(得分:0)
我有两个想法,您可以尝试...
1)Angular组件具有一个可以接收.scss文件的stylesUrls。但是,似乎无法轻松替换stylesUrl属性。但是,您可以轻松地换出组件本身...
基本上,您的实际应用程序将包装在“外壳”应用程序中,该应用程序仅负责提取正确的.scss文件。更具体地说,它将被包裹在2个不同的外壳中,每种样式分别包装一个。
@Component({
selector: 'style-one-page',
templateUrl: './app.component.html',
styleUrls: ['./app-style-one-page.scss']
})
export class WrapperStyleOneComponent extends PageComponent {}
@Component({
selector: 'style-two-page',
templateUrl: './app.component.html',
styleUrls: ['./app-style-two-page.scss']
})
export class WrapperStyleTwoComponent extends PageComponent {}
然后将这两个组件换掉是很简单的。
2)我的第二个想法是利用Angular Material Themes,可以很容易地将它们替换为这样:
@import '~@angular/material/theming';
@import 'themes-palettes';
@import 'themes-common';
@include mat-core();
@function custom-light-theme() {
@return (
primary: $primary-palette,
accent: $accent-palette,
warn: $warn-palette,
foreground: $foreground-palette,
background: $background-palette,
is-dark: false
);
}
$custom-light-theme: custom-light-theme();
@include angular-material-theme($custom-light-theme);
.dark-theme {
$mat-dark-theme: mat-dark-theme($dark-primary-palette, $dark-accent-palette, $dark-warn-palette);
@include angular-material-theme($mat-dark-theme);
}
答案 4 :(得分:0)
一个可行的想法。 (origin)
应该用于更改环境文件,但我想它也应该适用于样式。
您可以在angular.json中使用fileReplacements
来更改样式文件,但这需要您每次重新构建应用程序。
项目>公共>架构师>构建>配置
"customerA": {
"fileReplacements": [
{
"replace": "src/styles.scss",
"with": "assets/styles/customerA/_themes.scss"
}
]
},
"customerB": {
"fileReplacements": [
{
"replace": "src/styles.scss",
"with": "assets/styles/customerB/_themes.scss"
}
]
}
项目>公共>架构师>服务>配置
"customerA": {
"browserTarget": "public:build:customerA"
},
"customerB": {
"browserTarget": "public:build:customerB"
},
现在您可以运行ng serve -c customerA
或ng serve -c customerB
来获取相关的样式表。
准备好进行生产时,可以手动部署两次,也可以尝试遵循this idea for translating an angular app。
P.S。如果仅需要更改几种样式,则建议您使用css variables。