首页 文章

扩展/覆盖可重复使用的angular2组件的样式

提问于
浏览
30

假设我们想在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” . 如果我们在应用程序中使用此组件,我们可能希望覆盖/扩展某些样式,而无需复制和操作组件本身 . 这该怎么做?

Possible Solution 1: Set the Encapsulation to "ViewEncapsulation.None":
这不是一个真正的解决方案,只是一种解决方法 .

Possible Solution 2: Use "::shadow" or "/deep/" in CSS:
也可以,但根据WebComponent规范弃用了它 .

Possible Solution 3: Use global CSS and override the component CSS:
也可以,但它违反了影子DOM概念 .

Possible Solution 4: Override directly in the template of parent component:

例:

<my-cmp [font-size]="100"></my-cmp>

如果我们做了很多重写,那真的不合适 .

Possible Solution 5: Override or extend the "@Component" definition with an additional stylesheet somehow:
这似乎是唯一正确的解决方案(至少对我而言) . 但我不知道该怎么做......

有什么建议吗?也许我弄错了...谢谢 .

4 回答

  • 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);
      }
    }
    

    有关详细信息,请参阅此问题:

  • 7

    在Angular 4中,我们可以使用继承的类样式表中的 ::ng-deep 伪类选择器覆盖样式 .

    :host ::ng-deep element {
        //your style here
    }
    

    有关更多信息,请参阅http://blog.angular-university.io/angular-ngclass-ngstyle/

  • 7

    可能的解决方案2:在CSS中使用“:: shadow”或“/ deep /”:

    这仅适用于 ViewEncapsulation.Native .

    如果您使用 ViewEncapsulation.Emulated (默认),则Angular使用它自己对 /deep/::shadow 的解释,并且不适用弃用 .

    如果您使用 ViewEncapsulation.Native ,那么您目前运气不佳,因为浏览器原生 ::shadow/deep/ 深度已被弃用,而Angular尚未提供对 ViewEncapsulation.Native 的主题支持的任何支持,例如Polymer使用(polyfilled)CSS变量和mixins .

  • 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 {
    }
    

相关问题