在 Angular 中使用主机绑定注入样式声明
Inject Style Declarations Using Hostbinding in Angular
你们知道如何使用 @HostBinding 装饰器在组件中批量注入样式声明吗?
我正在尝试的是:
@HostBinding('style')
get style(): CSSStyleDeclaration {
return {
background: 'red',
color: 'lime'
} as CSSStyleDeclaration;
}
根据我的理解,这应该将背景和颜色样式注入组件,但它并没有...
我可以像这样控制单个样式声明:
@HostBinding('style.background') private background = 'red';
但我想为他们所有人做,请帮忙:P
这是完整代码:
@Component({
selector: 'my-app',
template: `
<div>
<h2>Hello world!</h2>
</div>
`,
})
export class App {
// This works
@HostBinding('style.color') private color = 'lime';
/* This does not work
@HostBinding('style')
get style(): CSSStyleDeclaration {
return {
background: 'red'
} as CSSStyleDeclaration;
}
*/
constructor() {}
}
和一个正在工作的 plunker:
https://plnkr.co/edit/CVglAPAMIsdQjsqHU4Fb?p=preview
您需要传递与添加到 <div style="...">
和 sanitize 样式元素相同的值
@HostBinding('style')
get myStyle(): SafeStyle {
return this.sanitizer.bypassSecurityTrustStyle('background: red; display: block;');
}
constructor(private sanitizer:DomSanitizer) {}
如果您想将多个 css 样式作为字符串或作为带有 cammelCase 约定的 object 传递,这里有一个解决方案:
Parent HTML
<app-button [style]="styleFromParent">Some button</app-button>
Parent 组件有 styleFromParent
属性 并且如果 属性 在某些时候发生变化,它会进行模拟:
Parent 组件 TS
import { Component, OnInit, ChangeDetectorRef } from '@angular/core';
@Component({
selector: 'app-site-panel',
templateUrl: './site-panel.component.html',
})
export class SitePanelComponent implements OnInit {
constructor(private _detectChanges: ChangeDetectorRef) {}
styleFromParent = { marginTop: '10px', marginLeft: '50px' };
ngOnInit() {
setTimeout(() => {
this.styleFromParent = { marginTop: '20px', marginLeft: '1px' };
this._detectChanges.detectChanges();
}, 2000);
}
}
Child HTML
<ng-content></ng-content>
Child 组件 TS
import { Component, OnInit, HostBinding, Input } from '@angular/core';
import { DomSanitizer, SafeStyle } from '@angular/platform-browser';
@Component({
selector: 'app-button',
templateUrl: './button.component.html',
})
export class ButtonComponent implements OnInit {
@HostBinding('style') baseStyle: SafeStyle;
@Input()
set style(style: string | object) {
let mappedStyles = style as string;
if (typeof style === 'object') {
mappedStyles = Object.entries(style).reduce((styleString, [propName, propValue]) => {
propName = propName.replace(/([A-Z])/g, matches => `-${matches[0].toLowerCase()}`);
return `${styleString}${propName}:${propValue};`;
}, '');
this.baseStyle = this.sanitizer.bypassSecurityTrustStyle(mappedStyles);
} else if (typeof style === 'string') {
this.baseStyle = this.sanitizer.bypassSecurityTrustStyle(mappedStyles);
}
}
constructor(private sanitizer: DomSanitizer) {}
ngOnInit() {}
}
在上面你可以看到 baseStyle
有 HostBinding
到 style
组件绑定。
当 style
输入通过时 setter 将触发,检查是否传递了字符串或 object,将其解析为字符串并清理 css 并将其分配给 baseStyle
因此主持人风格将发生变化。
你们知道如何使用 @HostBinding 装饰器在组件中批量注入样式声明吗? 我正在尝试的是:
@HostBinding('style')
get style(): CSSStyleDeclaration {
return {
background: 'red',
color: 'lime'
} as CSSStyleDeclaration;
}
根据我的理解,这应该将背景和颜色样式注入组件,但它并没有...
我可以像这样控制单个样式声明:
@HostBinding('style.background') private background = 'red';
但我想为他们所有人做,请帮忙:P
这是完整代码:
@Component({
selector: 'my-app',
template: `
<div>
<h2>Hello world!</h2>
</div>
`,
})
export class App {
// This works
@HostBinding('style.color') private color = 'lime';
/* This does not work
@HostBinding('style')
get style(): CSSStyleDeclaration {
return {
background: 'red'
} as CSSStyleDeclaration;
}
*/
constructor() {}
}
和一个正在工作的 plunker: https://plnkr.co/edit/CVglAPAMIsdQjsqHU4Fb?p=preview
您需要传递与添加到 <div style="...">
和 sanitize 样式元素相同的值
@HostBinding('style')
get myStyle(): SafeStyle {
return this.sanitizer.bypassSecurityTrustStyle('background: red; display: block;');
}
constructor(private sanitizer:DomSanitizer) {}
如果您想将多个 css 样式作为字符串或作为带有 cammelCase 约定的 object 传递,这里有一个解决方案:
Parent HTML
<app-button [style]="styleFromParent">Some button</app-button>
Parent 组件有 styleFromParent
属性 并且如果 属性 在某些时候发生变化,它会进行模拟:
Parent 组件 TS
import { Component, OnInit, ChangeDetectorRef } from '@angular/core';
@Component({
selector: 'app-site-panel',
templateUrl: './site-panel.component.html',
})
export class SitePanelComponent implements OnInit {
constructor(private _detectChanges: ChangeDetectorRef) {}
styleFromParent = { marginTop: '10px', marginLeft: '50px' };
ngOnInit() {
setTimeout(() => {
this.styleFromParent = { marginTop: '20px', marginLeft: '1px' };
this._detectChanges.detectChanges();
}, 2000);
}
}
Child HTML
<ng-content></ng-content>
Child 组件 TS
import { Component, OnInit, HostBinding, Input } from '@angular/core';
import { DomSanitizer, SafeStyle } from '@angular/platform-browser';
@Component({
selector: 'app-button',
templateUrl: './button.component.html',
})
export class ButtonComponent implements OnInit {
@HostBinding('style') baseStyle: SafeStyle;
@Input()
set style(style: string | object) {
let mappedStyles = style as string;
if (typeof style === 'object') {
mappedStyles = Object.entries(style).reduce((styleString, [propName, propValue]) => {
propName = propName.replace(/([A-Z])/g, matches => `-${matches[0].toLowerCase()}`);
return `${styleString}${propName}:${propValue};`;
}, '');
this.baseStyle = this.sanitizer.bypassSecurityTrustStyle(mappedStyles);
} else if (typeof style === 'string') {
this.baseStyle = this.sanitizer.bypassSecurityTrustStyle(mappedStyles);
}
}
constructor(private sanitizer: DomSanitizer) {}
ngOnInit() {}
}
在上面你可以看到 baseStyle
有 HostBinding
到 style
组件绑定。
当 style
输入通过时 setter 将触发,检查是否传递了字符串或 object,将其解析为字符串并清理 css 并将其分配给 baseStyle
因此主持人风格将发生变化。