假设我们想在angular2中使用某个库中的组件(例如来自material2)。组件注释如下所示:
@Component({
moduleId: module.id,
selector: 'md-input',
templateUrl: 'input.html',
styleUrls: ['input.css'],
providers: [MD_INPUT_CONTROL_VALUE_ACCESSOR],
host: {'(click)' : 'focus()'}
})
此组件附带“默认”样式表“input.css”。如果我们在应用程序中使用此组件,我们可能希望覆盖/扩展某些样式,而无需复制和操作组件本身。怎么做?
可能的解决方案1:将封装设置为“ViewEncapsulation.None”:
这不是一个真正的解决方案,只是一种解决方法。
可能的解决方案2:在CSS中使用“:: shadow”或“/ deep /”:
也可以,但根据WebComponent规范弃用了它。
可能的解决方案3:使用全局CSS并覆盖组件CSS:
也可以,但它违反了影子DOM概念。
可能的解决方案4:直接在父组件的模板中覆盖:
示例:
<my-cmp [font-size]="100"></my-cmp>
如果我们做了很多重写,那是不是真的适合。
可能的解决方案5:以某种方式使用其他样式表覆盖或扩展“@Component”定义:
这似乎是唯一正确的解决方案(至少对我而言)。但我不知道该怎么做......
对此有何建议?也许我有点不对劲...... 感谢。
答案 0 :(得分:12)
在Angular 4中,我们可以使用继承的类样式表中的::ng-deep
伪类选择器覆盖样式。
:host ::ng-deep element {
//your style here
}
有关更多信息,请参阅http://blog.angular-university.io/angular-ngclass-ngstyle/
答案 1 :(得分:11)
对于解决方案5,您需要为目标组件创建一个子类,创建一个自定义装饰器来处理/覆盖元数据并为当前子组件设置它。
以下是一个示例:
@CustomComponent({
styleUrls: ['css/style.css']
})
export class OverridenComponent extends SomeComponent {
}
CustomComponent
装饰器看起来像这样:
export function CustomComponent(annotation: any) {
return function (target: Function) {
var parentTarget = Object.getPrototypeOf(target.prototype).constructor;
var parentAnnotations = Reflect.getMetadata('annotations', parentTarget);
var parentAnnotation = parentAnnotations[0];
Object.keys(parentAnnotation).forEach(key => {
if (!isPresent(parentAnnotation[key])) {
annotation[key] = parentAnnotation[key];
}
});
var metadata = new ComponentMetadata(annotation);
Reflect.defineMetadata('annotations', [ metadata ], target);
}
}
有关详细信息,请参阅此问题:
答案 2 :(得分:7)
可能的解决方案2:在CSS中使用“:: shadow”或“/ deep /”:
仅当您使用ViewEncapsulation.Native
时才适用。
如果您使用ViewEncapsulation.Emulated
(默认),则Angular会使用它自己对/deep/
和::shadow
的解释,弃用不适用。
如果您使用ViewEncapsulation.Native
,那么您目前运气不佳,因为浏览器原生::shadow
和/deep/
深度已被弃用,Angular尚未提供对{的主题支持的任何支持{1}}例如,Polymer使用(polyfilled)CSS变量和mixins。
答案 3 :(得分:7)
从Angular 2.3开始,我们可以使用组件继承。为了完成您的解决方案5,我们可以做到这一点。
//This is our base component that we want to override
@Component({
selector: 'pagination',
templateUrl: './pagination.component.html',
styleUrls: ['./pagination.component.css']
})
export class PaginationComponent {
}
//This inherits from our base component and uses a different style sheet.
@Component({
selector: 'pagination2',
//This is sharing the template with the parent class. Note
//this needs to be included since templateUrl doesn't automatically
//inherit.
templateUrl: './pagination.component.html',
//This is using a unique css file
styleUrls: ['./pagination2.component.css']
})
export class PaginationComponent2 extends PaginationComponent {
}