使用可重用组件时,Angular 7 CSS无法正常工作

时间:2019-02-03 15:39:38

标签: javascript css angular angular7

我是Angular的新手,来自React.js背景。

我制作了一个简单的网格组件,如下所示:

grid.component.js

import { Component, OnInit, Input } from '@angular/core';

@Component({
  selector: 'app-grid',
  template: `
    <div [ngStyle]="styles()" [ngClass]="passClass">
      <ng-content></ng-content>
    </div>
  `,
  styles: [`
    div {
      display: flex;
    }
  `]
})
export class GridComponent implements OnInit {
  @Input() direction: string;
  @Input() justify: string;
  @Input() align: string;
  @Input() width: string;
  @Input() passClass: string;

  constructor() { }

  ngOnInit() {
  }

  styles() {
    return {
      'flex-direction': this.direction || 'row',
      'justify-content': this.justify || 'flex-start',
      'align-items': this.align || 'flex-start',
      ...(this.width && { width: this.width })
    };
  }
}

我想在其他组件中使用它,如下所示: aboutus.component.html

<app-grid passClass="about-us page-container">
  <app-grid direction="column" passClass="left">
    <div class="title blue bold">
      An open community For Everyone
    </div>
    <div class="large-desc grey">
      This conference is brought to you by
      the Go Language Community in
      India together with the Emerging
      Technology Trust (ETT). ETT is a non-
      profit organization, established to
      organize and conduct technology
      conferences in India. It’s current
      portfolio includes
    </div>
  </app-grid>
</app-grid>

aboutus.component.sass

.about-us
  position: relative
  .left
    width: 50%
    &:after
      bottom: 0
      right: 0
      z-index: 0
      margin-right: -5vw
      position: absolute
      content: url(../../assets/images/footer.svg)

但是,发生的是第二个组件附带的CSS无法工作。

我对CSS隔离有所了解,但不知道它是否会影响到这里。

P.S .:请随时提供有关此问题范围以外内容的反馈。

3 个答案:

答案 0 :(得分:3)

不可能将CSS类作为变量传递到模板中。因此,如果您对aboutus.component.html的期望是能够将left CSS类作为模板中的变量进行传递,那将不起作用。

我可以指出一些希望对您有帮助的事情:

  1. 如果要从组件外部修改组件内部的CSS类,一种选择是使用ng-deep

  2. 在您的特定情况下,我认为ng-deep不是必需的。我建议将div元素放在app-grid组件内,而应使用@HostBinding装饰器将样式应用于宿主元素。使用这种方法,您可以完全丢弃passCss,因为现在无论您在哪里使用app-grid组件,都可以使用app-grid选择器在CSS中对该组件进行样式设置。

    grid.component.ts:

    import { Component, OnInit, Input, HostBinding, SafeStyle } from '@angular/core';
    
    @Component({
      selector: 'app-grid',
      template: `<ng-content></ng-content>`,
      styles: [`
        :host {
          display: flex;
        }
      `]
    })
    export class GridComponent implements OnInit {
      @Input() direction: string;
      @Input() justify: string;
      @Input() align: string;
      @Input() width: string;
    
      constructor(private sanitizer:DomSanitizer) { }
    
      ngOnInit() {
      }
    
      @HostBinding('style')
      styles(): SafeStyle {
        const styles = `
          flex-direction: ${this.direction || 'row'};
          justify-content: ${this.justify || 'flex-start'};
          align-items: ${this.align || 'flex-start'};
       `;
        return this.sanitizer.bypassSecurityTrustStyle(styles);
      }
    }
    

    aboutus.component.sass:

      app-grid {
        // You can style the host element of a component
        // just like any native HTML element and without
        // needing to use `ng-deep`
      }
    
  3. 您可能还想研究CSS Custom Properties。自定义CSS属性不受视图封装的保护。如果可以的话,这使您能够为组件创建CSS API,并且这些属性可以在组件内的任何位置使用。

    aboutus.component.sass

    app-grid {
      --image: url(../../assets/images/footer.svg)
    }
    

    grid.component.sass

    div {
      content: var(--image);
    }
    

答案 1 :(得分:1)

如果要样式化其他组件中的某些元素,请使用:host/deep/修饰符(不推荐使用-Alternative to /deep/)。您可以在documentation

中阅读有关此功能的更多信息

在您的情况下,这应该可行:

:host /deep/ {
    .left {
        width: 50%
        &:after {
          bottom: 0
          right: 0
          z-index: 0
          margin-right: -5vw
          position: absolute
          content: url(../../assets/images/footer.svg)
       }
    }
}

您还可以禁用此组件的封装:

@Component({
  selector: 'app-grid',
  template: `
    <div [ngStyle]="styles()" [ngClass]="passClass">
      <ng-content></ng-content>
    </div>
  `,
  styles: [`
    div {
      display: flex;
    }
  `],
  encapsulation: ViewEncapsulation.None
})

答案 2 :(得分:0)

我有一个替代解决方案,尽管范围可能略有不同,因为它要求您创建并加载CSS文件,而不是在组件模板中定义HTML / CSS。这样做的好处是,您可以将共享的CSS文件存储在共享文件夹中,然后在其他模块中重复使用该CSS文件。

例如

@Component({
   selector: 'first',
   template: `
    <div [ngStyle]="styles()" [ngClass]="passClass">
      <ng-content></ng-content>
    </div>
  `,
   styleUrls: ["sample.style.css, /shared/shared2.style.css"]
})
export class SampleComponent {}

您可以在SO上参考其他post以获得更多详细信息。它为跨模块和组件共享样式的各种方式提供了利弊。