【问题标题】:How to conditionally apply styles on the component tag based on the visibility of component contents?如何根据组件内容的可见性有条件地在组件标签上应用样式?
【发布时间】:2020-05-18 16:08:36
【问题描述】:

假设我有一个像这样的组件,其中包含显示或隐藏组件内内容的逻辑:

@Component({
  selector: 'hello',
  template: `<div *ngIf="visible"> <h1>Hello {{name}}!</h1></div>`,
  styles: [`h1 { font-family: Lato; } div { border: 1px solid blue }`]
})
export class HelloComponent  {
  @Input() name: string;
  visible: boolean;
  ngOnInit() {
    this.visible = this.name === "Stranger"
  }
}

我在另一个组件中这样使用它:

<div class="container">
  <hello class='hello-class' name="Stranger"></hello>

  <!-- This will not be visible -->
  <hello class='hello-class' name="Not stranger"></hello>
</div>

我将一些样式应用于hello 组件,如下所示:

.hello-class {
  display: block;
  margin-bottom: 80px;
}

hello 组件的第二次使用将因为组件中的条件而变得不可见。但即使组件不可见,我添加到 hello-class 的样式也会应用于组件。

我无法移动条件以将组件显示/隐藏到父级。所以我不能在组件之前做一个*ngIf

有什么方法可以让我只在组件可见的情况下应用这种样式?

这里是说明问题的 stackblitz 的链接:https://stackblitz.com/edit/angular-ivy-mfrb7j

【问题讨论】:

  • 在什么情况下显示/隐藏相应的 hello 组件?
  • @AkhilChandran:基于一些逻辑在hello组件内部。
  • 你能把你使用的逻辑添加到问题中吗?
  • @AkhilChandran 它已经在代码(visible 属性)和 stackblitz 链接中。

标签: javascript css angular typescript


【解决方案1】:

由于没有子元素,您可以使用 css 选择器来做到这一点:

.hello-class:not(:empty) {
  display: block;
  margin-bottom: 80px;
}

通过使用:not(:empty),它检查元素(组件的宿主元素)是否有子元素。如果它没有子元素,则该样式将不适用。

https://developer.mozilla.org/en-US/docs/Web/CSS/:empty

【讨论】:

    【解决方案2】:

    使用 ngClass 的条件样式也适用于这种情况。

    所以在你的 HTML 中你会写:

    <div class="container">
      <hello [ngClass]="{'hello-class': visible}" name="Stranger"></hello>
    
      <!-- This will not be visible -->
      <hello [ngClass]="{'hello-class': visible}" name="Not stranger"></hello>
    </div>
    

    所以当 visible = true 时,它​​将应用 'hello-class' 样式。


    下面的扩展答案

    选项 1:

    自定义属性绑定和 ngClass

    hello.component.ts - 使父组件中的“可见”属性可绑定:

    @Component({
      selector: 'hello',
      template: `<div *ngIf="visible"> <h1>Hello {{name}}!</h1></div>`,
      styles: [`h1 { font-family: Lato; } div { border: 1px solid blue }`]
    })
    export class HelloComponent  {
      @Input() name: string;
      @Input() visible: boolean;
      ngOnInit() {
        this.visible = this.name === "Stranger"
      }
    }
    

    parent.component.html - 绑定到 hello 组件的 "visible" 属性并使用 ngClass 应用条件样式:

    <div class="container">
      <hello [visible]="visibility" [ngClass]="{'hello-class': visibility}" name="Stranger"></hello>
    
      <!-- This will not be visible -->
      <hello [visible]="visibility" [ngClass]="{'hello-class': visibility}" name="Not stranger"></hello>
    </div>
    

    parent.component.ts - 添加本地属性“可见性”:

    visibility: boolean;
    

    选项 2

    本地参考和 ngClass

    或者,如果您无法向 parent.component.ts 文件添加任何内容,您可以在 html 中完成所有操作。为此,您也不需要将 @Input() 装饰器添加到您的 hello.component.ts 文件中。看起来有点粗糙,但确实有效。

    parent.component.html - 使用本地引用来触发 ngClass 的条件:

        <div class="container">
      <hello #a [ngClass]="{'hello-class': a.visible}" name="Stranger"></hello>
    
      <hello #b [ngClass]="{'hello-class': b.visible}" name="Not stranger"></hello>
    </div>
    

    【讨论】:

    • 这意味着我需要将显示/隐藏组件(visible 标志)的逻辑移动到父组件。这在我的场景中是不可能的。
    • 你能向父组件添加任何类型的属性吗?如可见性:布尔值;
    • 不,这是我在问题中提到的约束。逻辑必须包含在子组件中。您的答案中的选项 2 可能有效。
    【解决方案3】:

    将组件的名称输入附加到变量。

    public helloNames = [ 'Stranger', 'Not stranger'];
    

    然后在组件中,执行以下操作。

    <div class="container">
      <hello class='hello-class' *ngIf="helloNames[0] == 'Stranger'" name="helloNames[0]"></hello>
    
      <!-- This will not be visible -->
      <hello class='hello-class' *ngIf="helloNames[1] == 'Stranger'" name="helloNames[1]"></hello>
    </div>
    

    【讨论】:

    • 这会将显示/隐藏组件的逻辑转移到父级——这是我不想要的。
    猜你喜欢
    • 2016-09-03
    • 1970-01-01
    • 2018-08-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多