Cannot Understand the Use of :host in components i

2020-02-26 09:57发布

问题:

What i have understood of host is that if i have a child component inside a parent component and we want to style a child component from the parent component we can use :host . and :host-context for vice-versa. Please let me know if this is the right use of host .

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

When i try to do the same in my App it dosent work

App component template

  <div class ="top">
    <h1>
      Home Component
    </h1>
    <hr>
    <app-ngrx></app-ngrx>
    <router-outlet></router-outlet>
  <div>

ngrx component template

  <h3 class="mine">NGRX</h3>

<button (click)="increment()">Increment</button>
<div>Current Count: {{ counter | async }}</div>
<button (click)="decrement()">Decrement</button>

<button (click)="reset()">Reset Counter</button>

App component CSS

:host(.mine){
  color:red;
}

This do not Seem to work Please help i am not able to understand.

I looked at this question But just not able to figure out

Angular 2: How to style host element of the component?

Updated after @Gunter Answer

In my app-ngrx template i have added

  <h3 class = "mine">NGRX</h3>

<button (click)="increment()">Increment</button>
<div>Current Count: {{ counter | async }}</div>
<button (click)="decrement()">Decrement</button>

<button (click)="reset()">Reset Counter</button>

and in the app-ngrx css file i have added

:host(.mine){
  color:red;
}

But even without adding mine in app component like

<app-ngrx></app-ngrx>

The h3 is red where as i feel it should be red when <app-ngrx class = "mine"></app-ngrx>

回答1:

What i have understood of host is that if i have a child component inside a parent component and we want to style a child component from the parent component we can use :host . and :host-context for vice-versa

No, this is not what it used for.

:host selector comes from shadow DOM spec.

...This scoped subtree is called a shadow tree. The element it's attached to is its shadow host.

In angular world, a component's template is a shadow tree. The component's element is a shadow host. So when you're defining styles for :host selector, the styles are applied to the component's element.

:host

In your example, if you defined styles in my-app component, the styles will be applied to <my-app> DOM element. This particular configuration:

:host(.mine){
  color:red;
}

Will be applied to the host element that has .mine class:

<my-app class="active">

If you defined styles in app-ngrx component, the styles will be applied to <app-ngrx> DOM element, NOT <my-app>. This particular configuration:

:host(.mine){
  color:red;
}

Will be applied to the host element that has .mine class:

<app-ngrx class="active">

:host-context

Now, :host-context is also applied to the host element, but the function (parenthesis) takes a selector that is checked not against the host element itself, but against all ancestors up to document root. If such element is found, the styles are applied.

For example, this selector

:host(.mine){
  color:red;
}

matches such structure:

<my-app class="mine">

whereas, this selector:

:host-context(.mine){
  color:red;
}

matches this structure:

<div class="mine">
 ...
   <my-app>

This is useful, if you want to apply styles to components view (shadow root) conditionally. This makes h2 always bold:

h2 {
   font-weight: bold;
}

whereas this

:host-context(.make-inner-components-bold) h2 {
  font-weight: bold;
}

makes them bold only if your component is inside an element with class .make-inner-components-bold.



回答2:

  • :host { ... } selects the component itself
  • :host(.mine) { ... } selects the component itself when it has class="mine" set

  • :host-context(.mine) { ... } selects the component itself when one of its ancestors has class="mine" set

See also https://angular.io/docs/ts/latest/guide/component-styles.html

@Component({
  selector: 'h3', 
  styles: [':host(.mine) { color: red; }], 
  template: '<ng-content></ng-content>'}) 
class MyH3Component{}
<h3 class="mine">this is red</h3>
<h3>this is black</h3>

or with :host-context

@Component({
  selector: 'h3', 
  styles: [':host-context(.mine) { color: red; }], 
  template: '<ng-content></ng-content>'}) 
class MyH3Component{}

<body class="mine">
  <my-app><my-app>
<body>

AppComponent

template: '<h3>this is red</h3>'

or with class="mine" set

<body>
  <my-app><my-app>
<body>

AppComponent

template: '<h3>this is black</h3>'

update

If you want to style the content of a child component (instead of the child component itself) you can use /deep/

:host child /deep/ h3 {
  color: red;
}

update 2 ::slotted is now supported by all new browsers and can be used with `ViewEncapsulation.ShadowDom

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



标签: css angular