Wie und wo :: ng-deep verwenden?


90

Ich bin neu in Angular 4, kann jemand bitte erklären, wie und wo ::ng-deepin Angular 4 zu verwenden ist?

Eigentlich möchte ich einige der CSS-Eigenschaften der untergeordneten Komponenten von den übergeordneten Komponenten überschreiben. Außerdem wird es auf IE11 unterstützt?


Da /deep/und ::ng-deepbeide sind veraltet, empfehle ich Ihnen auf diese Antwort zu nehmen alook stackoverflow.com/a/49308475/2275011 für weitere Details und Lösungen und Kommentare.
Ferie

Antworten:


92

Normalerweise /deep/ “shadow-piercing”kann ein Kombinator verwendet werden, um einen Stil auf zu erzwingen child components. Dieser Selektor hatte einen Alias ​​>>> und jetzt einen anderen mit dem Namen :: ng-deep.

Da /deep/ combinatores veraltet ist, wird empfohlen, es zu verwenden::ng-deep

Zum Beispiel:

<div class="overview tab-pane" id="overview" role="tabpanel" [innerHTML]="project?.getContent( 'DETAILS')"></div>

und css

.overview {
    ::ng-deep {
        p {
            &:last-child {
                margin-bottom: 0;
            }
        }
    }
}

Es wird auf untergeordnete Komponenten angewendet


Unterstützt es IE11?
Jeyabalan Thavamani

2
Angular analysiert es - Sie müssen sich also keine Gedanken über die Kompatibilität machen.
Simon_Weaver

ist es nur für untergeordnete Komponenten? Wie ich mich erinnere und wie ich in einem anderen Kommentar sehe, ist es auch für Dom-Elemente außerhalb der Komponente.
Yaya

Ich kann bestätigen, dass es auch übergeordnete Komponenten enthält ... Hatte gerade den Fall und war darüber verärgert.
Shadoweb

1
Super, es hat perfekt funktioniert.
Alfredo Zamudio

70

VERWENDUNG

::ng-deep, >>>Und /deep/deaktivieren Ansicht Kapselung für bestimmte CSS - Regeln, mit anderen Worten, es gibt Sie auf DOM - Elemente zuzugreifen, die nicht der HTML - Code in Ihrer Komponente sind. Wenn Sie beispielsweise Angular Material (oder eine andere Bibliothek von Drittanbietern wie diese) verwenden, befinden sich einige generierte Elemente außerhalb des Bereichs Ihrer Komponente (z. B. Dialogfeld ), und Sie können nicht direkt oder mithilfe eines normalen CSS auf diese Elemente zugreifen Weg. Wenn Sie die Stile dieser Elemente ändern möchten, können Sie eines dieser drei Dinge verwenden, zum Beispiel:

::ng-deep .mat-dialog {
  /* styles here */
}

Derzeit empfiehlt das Angular-Team, "tiefe" Manipulationen nur mit EMULATED- Ansichtskapselung durchzuführen .

MISSBILLIGUNG

"tiefe" Manipulationen sind ebenfalls veraltet , ABER es funktioniert vorerst noch, da Angular die Vorverarbeitung unterstützt (beeilen Sie sich nicht, dies ::ng-deepheute abzulehnen , werfen Sie zuerst einen Blick auf die Abwertungspraktiken ).

Bevor Sie diesen Weg gehen, empfehle ich Ihnen, einen Blick auf das Deaktivieren des Ansatzes zur Ansichtskapselung zu werfen (was auch nicht ideal ist, da Ihre Stile in andere Komponenten eindringen können), aber in einigen Fällen ist dies ein besserer Weg. Wenn Sie die Ansichtskapselung deaktivieren möchten, wird dringend empfohlen, bestimmte Klassen zu verwenden, um Überschneidungen von CSS-Regeln zu vermeiden und schließlich ein Durcheinander in Ihren Stylesheets zu vermeiden. Es ist wirklich einfach, direkt in der .tsDatei der Komponente zu deaktivieren :

@Component({
  selector: '',
  template: '',
  styles: [''],
  encapsulation: ViewEncapsulation.None  // Use to disable CSS Encapsulation for this component
})

Weitere Informationen zur Ansichtskapselung finden Sie in diesem Artikel.


3
Durch Deaktivieren der Ansichtskapselung wird das gesamte CSS in Ihrer Komponente global angewendet.
Vedran

17
Nicht benutzen ViewEncapsulation.None! Es wird viel Schaden anrichten, wenn diese Stile in andere Komponenten eindringen können.
Alex Klaus

1
@AlexKlaus, stimme zu, deshalb habe ich in der Antwort erwähnt, dass es nicht ideal ist. Eigentlich habe ich es nur einmal verwendet, um gemeinsam genutzte wiederholbare Stile auf Angular Material-Komponenten anzuwenden. Wenn Sie versuchen, die Kapselung zu deaktivieren, wird es möglicherweise irgendwann zu einem Durcheinander kommen. Es ist gut, über diese Option Bescheid zu wissen, aber verwenden Sie sie nicht, wenn Sie nicht sicher sind, ob Sie sie benötigen.
Kommerzieller Selbstmord

29

Ich möchte betonen, wie wichtig es ist, die ::ng-deepAnzahl der untergeordneten Elemente einer Komponente auf nur untergeordnete Elemente zu beschränken, indem der Elternteil eine gekapselte CSS-Klasse sein muss.

Damit dies funktioniert, ist es wichtig, das ::ng-deepNach dem übergeordneten Element zu verwenden, nicht vorher, da es sonst für alle Klassen mit demselben Namen gilt, sobald die Komponente geladen wird.

Komponente CSS:

.my-component ::ng-deep .mat-checkbox-layout {
    background-color: aqua;
}

Komponentenvorlage:

<h1 class="my-component">
    <mat-checkbox ....></mat-checkbox>
</h1>

Resultierende (Winkel generierte) CSS:

.my-component[_ngcontent-c1] .mat-checkbox-layout {
    background-color: aqua;
}

BEARBEITEN:

Sie können dasselbe Verhalten erzielen, indem Sie das :hostSchlüsselwort verwenden, anstatt eine neue CSS-Klasse zu erstellen.

:host ::ng-deep .mat-checkbox-layout

5
Mann, deine Antwort my-component ::ng-deep...hat mir gerade den Tag gerettet. Ich habe den ganzen Tag versucht, mit ng-deep einen Stil für meine Komponente anzuwenden, und habe alle Komponenten aus meiner gesamten Anwendung überschrieben.
Cristiano Bombazar

2
Bemerkenswert: "Um den angegebenen Stil auf die aktuelle Komponente und alle ihre Nachkommen [aber nicht global] zu übertragen, müssen Sie den :: host-Selektor vor :: ng-deep einschließen." Von: angle.io/guide/component-styles
StvnBrkdll

1
@CristianoBombazar - Sie erhalten das gleiche Verhalten mit dem :hostSchlüsselwort - hat der Antwort aus Gründen der Übersichtlichkeit einen Hinweis hinzugefügt.
Vedran

23

Verpassen Sie nicht die Erklärung, :host-contextdie sich direkt oben ::ng-deepin der Winkelführung befindet: https://angular.io/guide/component-styles . Haftungsausschluss: Ich habe es bis jetzt verpasst und wünschte, ich hätte es früher gesehen.

::ng-deepDies ist häufig erforderlich, wenn Sie die Komponente nicht geschrieben haben und keinen Zugriff auf ihre Quelle haben. Dies :host-contextkann jedoch eine sehr nützliche Option sein, wenn Sie dies tun.

Ich habe beispielsweise einen schwarzen <h1>Header in einer von mir entworfenen Komponente und möchte ihn in Weiß ändern können, wenn er auf einem dunklen Hintergrund angezeigt wird.

Wenn ich keinen Zugriff auf die Quelle hatte, muss ich dies möglicherweise in der CSS für das übergeordnete Element tun:

.theme-dark widget-box ::ng-deep h1 { color: white; }

Stattdessen :host-contextkönnen Sie dies innerhalb der Komponente tun .

 h1 
 {
     color: black;       // default color

     :host-context(.theme-dark) &
     {
         color: white;   // color for dark-theme
     }

     // OR set an attribute 'outside' with [attr.theme]="'dark'"

     :host-context([theme='dark']) &
     {
         color: white;   // color for dark-theme
     }
 }

Dies sucht überall in der Komponentenkette nach .theme-darkdem CSS und wendet es auf das h1 an, falls es gefunden wird. Dies ist eine gute Alternative, um sich zu sehr darauf zu verlassen, ::ng-deepwas zwar oft notwendig ist, aber ein Anti-Muster darstellt.

In diesem Fall &wird das durch das ersetzt h1(so funktioniert sass / scss), sodass Sie Ihr "normales" und thematisches / alternatives CSS direkt nebeneinander definieren können, was sehr praktisch ist.

Achten Sie darauf, die richtige Anzahl von zu erhalten :. Denn ::ng-deepes gibt zwei und :host-contextnur einen.


Sie können auch verwenden, :host(.theme-dark)wenn Sie theme-darkkeine übergeordneten Komponenten erben möchten . Dies hängt vollständig vom CSS-Design Ihrer Website ab. Auch Attribute können sehr nützlich sein und können auf raffinierte Weise allein in :host([theme='dark']:not([dayofweek='tuesday'))
CSS

Beachten Sie auch, dass dies den normalen CSS-Regeln folgt. Wenn Sie also eine Komponente wie oben beschrieben (mit Host-Kontext-CSS) in einem Container haben, der eine .theme-lightKlasse hat, wird diese wiederum in einem Container verschachtelt, der .theme-darkdiese weiterhin aufnimmt theme-darkund anwendet CSS. Dies ist jedoch eine großartige Lösung für Klassen vom Typ 'modernizr' oder wenn Sie ein Thema global und nur einmal festgelegt haben.
Simon_Weaver

Kann ich: host-context anstelle von :: ng-deep verwenden?
Wirbel

@eddy Ich bin im Moment zu müde, um das vollständig durchzudenken, aber der Host-Kontext ist fast wie ng-deep, aber ich gehe den DOM-Baum nach oben anstatt nach unten. Es ist also absolut nicht gleichwertig, aber Sie könnten
Simon_Weaver

2

Nur ein Update:

Sie sollten ::ng-deepstattdessen verwenden, /deep/was veraltet zu sein scheint.

Pro Dokumentation:

Der Schatten-durchdringende Nachkommen-Kombinator ist veraltet und die Unterstützung wird von den wichtigsten Browsern und Tools entfernt. Aus diesem Grund planen wir, die Unterstützung in Angular einzustellen (für alle 3 von / deep /, >>> und :: ng-deep). Bis dahin sollte :: ng-deep für eine breitere Kompatibilität mit den Tools bevorzugt werden.

Sie finden es hier


5
In diesem Text heißt es eindeutig: :: ng-deep ist ebenfalls veraltet: "Wir planen, die Unterstützung in Angular (für alle 3 von / deep /, >>> und :: ng-deep) einzustellen."
Adripanico

-2

Verwenden Sie :: ng-deep mit Vorsicht. Ich habe es in meiner gesamten App verwendet, um die Farbe der Symbolleiste für das Materialdesign in meiner App auf verschiedene Farben festzulegen, nur um festzustellen, dass die Farben der Symbolleiste beim Testen der App aufeinander zugehen. Finden Sie heraus, dass diese Stile global werden. Lesen Sie diesen Artikel. Hier ist eine funktionierende Codelösung, die nicht in andere Komponenten übergeht.

<mat-toolbar #subbar>
...
</mat-toolbar>

export class BypartSubBarComponent implements AfterViewInit {
  @ViewChild('subbar', { static: false }) subbar: MatToolbar;
  constructor(
    private renderer: Renderer2) { }
  ngAfterViewInit() {
    this.renderer.setStyle(
      this.subbar._elementRef.nativeElement, 'backgroundColor', 'red');
  }

}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.