如何在Angular组件装饰器中基于类内变量实现条件化styleUrls?
首先得明确,你原来的写法根本行不通——因为@Component装饰器是在组件类实例化之前就执行的,这时候类内部的condition还没初始化,更别提用this访问了。
下面给你两个符合需求的可行方案:
方案一:动态加载样式文件
通过Angular的Renderer2操作DOM,在组件初始化或条件变化时,动态加载对应的样式表并移除旧的:
import { Component, Renderer2, Inject, OnInit } from '@angular/core'; import { DOCUMENT } from '@angular/common'; @Component({ selector: 'foo', templateUrl: './foo.component.html' }) export class FooComponent implements OnInit { public condition = false; private activeStyle?: HTMLStyleElement; constructor( private renderer: Renderer2, @Inject(DOCUMENT) private document: Document ) {} ngOnInit() { this.switchStyle(this.condition); } public changeCondition(condition: boolean): void { this.condition = condition; this.switchStyle(condition); } private switchStyle(useStyle1: boolean) { // 移除已加载的样式 if (this.activeStyle) { this.renderer.removeChild(this.document.head, this.activeStyle); } // 加载目标样式文件 const targetUrl = useStyle1 ? './foo1.component.scss' : './foo2.component.scss'; this.activeStyle = this.renderer.createElement('link'); this.renderer.setAttribute(this.activeStyle, 'rel', 'stylesheet'); this.renderer.setAttribute(this.activeStyle, 'href', targetUrl); this.renderer.appendChild(this.document.head, this.activeStyle); } }
方案二:CSS类切换(更优雅)
把两套样式都引入组件,通过给组件宿主元素添加不同的类,让对应样式生效:
- 先在组件装饰器里引入两个样式文件:
@Component({ selector: 'foo', templateUrl: './foo.component.html', styleUrls: ['./foo1.component.scss', './foo2.component.scss'] })
- 修改两个样式文件,给样式加上宿主类前缀:
foo1.component.scss:
.using-style-1 & { /* 这里写foo1的所有样式 */ .title { color: #ff4081; font-size: 20px; } }
foo2.component.scss:
.using-style-2 & { /* 这里写foo2的所有样式 */ .title { color: #2196f3; font-size: 16px; } }
- 在组件类里用
HostBinding动态切换宿主类:
import { Component, HostBinding } from '@angular/core'; @Component({ selector: 'foo', templateUrl: './foo.component.html', styleUrls: ['./foo1.component.scss', './foo2.component.scss'] }) export class FooComponent { @HostBinding('class.using-style-1') get useStyle1() { return this.condition; } @HostBinding('class.using-style-2') get useStyle2() { return !this.condition; } public condition = false; public changeCondition(condition: boolean): void { this.condition = condition; } }
这种方案更符合Angular的样式封装机制,不会污染全局样式,推荐使用。
内容的提问来源于stack exchange,提问作者Mohamed Karkotly
相关产品推荐
相关产品推荐

