使用不同的 CSS 样式表动态更改 Angular 组件的样式

Posted

技术标签:

【中文标题】使用不同的 CSS 样式表动态更改 Angular 组件的样式【英文标题】:Dynamically changing the style of an Angular component using different CSS style sheets 【发布时间】:2021-09-15 17:13:15 【问题描述】:

我正在尝试对单页应用程序进行动态样式表更改以在 Angular 中工作。这个想法是创建不同的主题,并让用户在专用菜单中选择它们。可能有很多主题,所以请不要介意下面的示例只有两个变体。功能已准备就绪。到目前为止,我已经将所有样式收集在单个大型 scss 文件中,每个主题一个。 (请注意,我很清楚,在 Angular 中,您经常为每个组件将样式拆分为许多子 scss 文件。但为了使这个想法奏效,我希望将它们全部放在每个主题的单个文件中)。我的菜单正常工作,并使用本地存储让应用记住选择了哪个主题,因为必须重新加载网站才能使更改生效。

现在解决问题: 在 app.component.ts 中,样式表以标准格式定义(即 styleUrls: [filename])。当在那里使用静态文件路径/名称时,以及使用在 @component-code 之外定义的变量时,样式可以完美运行。但是对于动态主题更改,我从 localstorage 中简单地获取了变量:

var settingsString = localStorage.getItem('usergraphicsdata');
if (isDefined(settingsString)) 
  let myUserSettings = JSON.parse(settingsString);
  const themename = myUserSettings.theme;

这一切也都在那里工作。不同的 console.logs 确认它理解了它应该理解的一切。但是问题来了。

if(themename == "theme1")
    var stylePath = "./app.component_theme1.scss";
    var graphicFolder = '/assets/theme1/';
     else if(themename == "theme2")
    var stylePath = "./app.component_theme2.scss";
    var graphicFolder = '/assets/theme2/';
    
  

然后是 @component 及其 styleUrls: [stylePath]

由于某种原因不考虑 if 条件,结果总是首先声明的主题(在上述情况下为“theme1”)将处于活动状态。因此,如果我只是更改条件中的顺序,并将主题 2 的代码放在第一位,那么将为站点选择该代码,而不管实际从 localstorage 获取哪个主题变量

我也尝试了其他几种变体,但这个似乎最接近解决方案。 Angular 在运行时 contra 构建中限制样式更改可能是个问题吗?还是我忘记了 if 条件中的一些基本内容?

最好的问候和对不起我有限的英语。 每

【问题讨论】:

您尝试过 ngClass 和 ngStyle 方法吗? coryrylan.com/blog/introduction-to-angular-ngclass-and-ngstyle, ***.com/questions/68215977/angular-ngstyle, blog.angular-university.io/angular-ngclass-ngstyle, angular.io/api/common/NgClass#description 是的,在这些解决方案适合的几个标签中。但我认为,如果整个网站都改变主题,它们将是笨拙的工具。我必须在网站的大多数标签中设置大量的 ngclass 和 ngsyle 条件。可能有几十个具有不同样式表和图像文件夹的主题。 ngsyle/ngclass 似乎只对只有两种选择的有限更改有用。 您尝试开发的方法感觉非常符合 Angular。我不知道这是否可能,但我一直认为@Component-decorator 中的内容是不可更改的。它是组件类型的一部分,需要定义,因此是只读的。你检查过吗? 【参考方案1】:

为什么不用路由来解决呢?为每个主题复制组件,只是使用不同的 css 文件,但对所有这些组件使用相同的 html 文件,并在菜单中放置指向该组件的链接(具有特定主题)。附加值是主题名称也出现在 url 中,您可以轻松应用不同的逻辑,而不会让事情变得复杂(不同的打字稿文件)。

类似这样的:

@Component(
  selector: 'sunflower',
  templateUrl: './detail.component.html',
  styleUrls: ['./sunflower.component.scss']
)
export class SunflowerComponent 

@Component(
  selector: 'roses',
  templateUrl: './detail.component.html',
  styleUrls: ['./roses.component.scss']
)
export class RosesComponent 

如果你试过了,请分享你遇到的问题。

更新

我做了一个非常基本的演示(我已经测试过),你可以在这里找到它:

repo

保重,祝你好运。

【讨论】:

也许不同的选择器名称会导致错误,如果你不使用它们可能不会,也许你需要使用 谢谢qqtf。我尝试了您的建议,但没有立即成功。首先,似乎我不能将导出放在 if 条件中。 Angular 给了我红色文本:“模块解析失败:'import' 和 'export' 可能只出现在顶层”其次,如果我以不同的方式命名导出的类,似乎我必须在其他组件中做很多工作。截至目前,我在应用程序中找到了 16 个地方,我必须在这些地方构建检查从 app.component 发出的主题名称。不过,我会用这种方法多弄一些。如果我有任何进一步的,我会分享它。 /每 当然你会得到那个错误。您需要为每个“主题”(我给它取了一个花名)生成一个新组件,这意味着一个单独的文件,顶部只能有一个导入语句列表。复制粘贴显然是行不通的。您还需要添加一个路由器模块,在其中定义每个主题的路径:'sunflower'、'roses',您需要在 -tag 中构建您将使用的 routerlink-definition每个菜单项。每次单击新菜单项时,都会调用一个新组件,该组件将使用相同的 html-template 但使用不同的 css-one。 添加了示例 repo 来回答 再次感谢qqtf。我不是 Angular 专业人士,这对我来说很不直观,所以很抱歉没有理解你的提示。我稍后会尝试,但我可能遇到了我的 if:s 不起作用的可能原因:正如我所提到的,它在我的 ifs 的控制台回复中看起来很正确,但风格没有改变。现在我阅读了有关 ViewEncapsulation.None 的可能错误问题,并且样式一旦加载,就永远不会被删除。可能是设计使然。这可以解释我的问题。阅读有关“延迟加载”的内容,那里有一个页面,其中解决了它:“使用 Angular CLI 动态加载 CSS”

以上是关于使用不同的 CSS 样式表动态更改 Angular 组件的样式的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Angular 2 中动态更改 :host 中的 CSS?

Angular - 使用 ng 样式更改 css

JS 动态修改CSS 样式方法/全局

Javascript_动态修改css样式方法汇总

javascript 动态修改css样式方法汇总(四种方法)

如何使用 CSS 更改 Angular-UI Bootstrap Datepicker 弹出窗口的样式?