【问题标题】:Extend/Override style of reusable angular2 component可重用 angular2 组件的扩展/覆盖样式
【发布时间】:2016-09-30 19:01: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”。如果我们在我们的应用程序中使用这个组件,我们可能想要覆盖/扩展一些样式,而不复制和操作组件本身。如何做到这一点?

可能的解决方案 1:将封装设置为“ViewEncapsulation.None”:
这不是真正的解决方案,只是一种解决方法。

可能的解决方案 2:在 CSS 中使用“::shadow”或“/deep/”:
也可以,但根据 WebComponent 规范已弃用。

可能的解决方案 3:使用全局 CSS 并覆盖组件 CSS:
也可以,但它违反了 shadow DOM 概念。

可能的解决方案4:直接在父组件的模板中覆盖:

例子:

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

如果我们做了很多覆盖,那真的不合适。

可能的解决方案 5:以某种方式使用附加样式表覆盖或扩展“@Component”定义:
这似乎是唯一正确的解决方案(至少对我而言)。但我不知道该怎么做......

对此有何建议?也许我有什么不对... 谢谢。

【问题讨论】:

    标签: angular


    【解决方案1】:

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

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

    更多信息请参考http://blog.angular-university.io/angular-ngclass-ngstyle/

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        【解决方案3】:

        对于解决方案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);
          }
        }
        

        查看这个问题了解更多详情:

        【讨论】:

          【解决方案4】:

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

          这仅适用于您使用ViewEncapsulation.Native。

          如果你使用 ViewEncapsulation.Emulated(默认),那么 Angular 会使用它自己对 /deep/ 和 ::shadow 的解释,并且不推荐使用。

          如果您使用ViewEncapsulation.Native,那么您目前不走运,因为浏览器原生::shadow 和/deep/ deep 已被弃用,并且Angular 还没有为ViewEncapsulation.Native 提供任何主题支持,例如Polymer使用(填充)CSS 变量和 mixins。

          【讨论】:

          猜你喜欢
          • 2017-11-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-01-04
          • 2013-12-13
          • 2019-04-17
          • 2020-02-01
          相关资源
          最近更新 更多