将外部CSS样式加载到Angular 2 Component中

时间:2015-12-31 06:29:15

标签: angular

import {Component} from 'angular2/core';

@Component({
    selector: 'my-app',
    template: '<div></div>',
    styleUrls: [
        'http://domain.com/external.css',
        'app/local.css'
    ]
})
export class AppComponent {}

external.css无法加载。有没有办法在Angular 2 Component中加载外部css?

5 个答案:

答案 0 :(得分:84)

另见https://angular.io/docs/ts/latest/guide/component-styles.html

查看封装

要允许外部样式影响组件的内容,您可以更改视图封装(这是什么阻止样式到&#34;流入&#34;组件)。

@Component({
    selector: 'some-component',
    template: '<div></div>',
    styleUrls: [
        'http://example.com/external.css',
        'app/local.css'
    ], 
    encapsulation: ViewEncapsulation.None, 
})
export class SomeComponent {}

查看封装符合目的。更好的方法是将样式直接添加到它们应该影响的组件中。 每个组件设置ViewEncapsulation,在某些情况下可能会派上用场。

&#34;阴影穿孔&#34;

您还可以使用阴影穿孔CSS组合器::ng-deep(不推荐使用>>>/deep/)来构建跨组件边界的选择器,例如

:host ::ng-deep .ng-invalid {
  border-bottom: solid 3px red;
}

对当前组件中具有类ng-invalid的所有标记设置样式,或者对任何具有红色下划线的后代设置样式,无论封装是None还是Emulated。这取决于浏览器支持/deep/是否与Native一起使用(据我所知,任何浏览器都不支持此功能)。

注意

阴影穿孔CSS组合器类似于shadow DOM规范中的组合,因为它们已经被弃用了很长一段时间。

使用默认 ViewEncapsulation.Emulated使用Angulars自己的/deep/::shadow实施,即使Chrome移除了原生支持,它们也能正常工作。

使用ViewEncapsulation.Native Angular使用Chromes shadow DOM CSS组合器(只有Chrome支持它们AFAIK)。如果Chrome最终将其删除,那么他们也不会在Angular中工作(仅限ViewEncapsulation.Native)。

全球风格

全局添加的样式(index.html)不考虑组件边界。 Angular2不会重写此类样式,ViewEncapsulation.Emulated不适用于它们。只有设置了ViewEncapsulation.Native并且浏览器具有原生阴影DOM支持,全局样式才能进入。

另请参阅此相关问题https://github.com/angular/angular/issues/5390

答案 1 :(得分:11)

首先 - styles / styleUrls只应用于任何直接影响模板元素样式的css规则。

您的external.css未应用于您的组件的原因是因为当您从styleUrlsstyles在external.css中加载这些规则时,在编译时,angular2将附加一个唯一的组件标识符,如归属选择器的归属选择器。

例如,在您的external.css中,如果存在div.container { /*some rules*/ }之类的规则,它将变为div.container[_ngcontent-cds-2] { /*some rules*/ }。因此,无论你如何努力强迫你的规则成为优先规则,例如添加!important标记,它不会起作用 - external.css中的所有选择器都被限制在属性选择器的一个级别,只有组件元素具有相同的属性。这就是angular2将样式限制为仅当前组件的方式。

当然总有一种解决方法。

这是我的解决方案 - 我将为所有js脚本添加外部资源服务,它将使用SystemJS加载AMD或全局,对于所有css文件,它将使用普通javascript以创建<link>元素并将其附加到<head>元素。

以下是我需要考虑的代码:

loadCSS(url) {
  // Create link
  let link = document.createElement('link');
  link.href = url;
  link.rel = 'stylesheet';
  link.type = 'text/css';
  
  let head = document.getElementsByTagName('head')[0];
  let links = head.getElementsByTagName('link');
  let style = head.getElementsByTagName('style')[0];
  
  // Check if the same style sheet has been loaded already.
  let isLoaded = false;  
  for (var i = 0; i < links.length; i++) {
    var node = links[i];
    if (node.href.indexOf(link.href) > -1) {
      isLoaded = true;
    }
  }
  if (isLoaded) return;
  head.insertBefore(link, style);
}

答案 2 :(得分:4)

这可能会迟到,希望这有助于其他人。要使用ViewEncapsulation,只需使用  import { ViewEncapsulation } from '@angular/core';

答案 3 :(得分:1)

此处已发布更好的方法:https://stackoverflow.com/a/36265072/5219412

您只需在组件的声明中添加:

@Component({
    ...
    encapsulation: ViewEncapsulation.None,
})

如角度文档中所述:https://angular.io/guide/component-styles

希望它有所帮助。

答案 4 :(得分:-1)

这里有很多复杂的答案,但是我一直发现,如果我想创建一些影响多个组件的样式,则实际上是一种全局样式,因此将其添加到styles.css中。该css文件很特殊,因为它不使用样式封装,因此会影响每个组件。

从概念上讲,这对我来说似乎可以,只是您必须谨慎使用,否则styles.css太大。

丰富