Jak i gdzie używać :: ng-deep?


90

Jestem nowy w Angular 4, więc czy ktoś mógłby wyjaśnić, jak i gdzie używać ::ng-deepAngular 4?

Właściwie chcę nadpisać niektóre właściwości CSS komponentów potomnych z komponentów nadrzędnych. Co więcej, czy jest obsługiwany w IE11?


Ponieważ oba /deep/i ::ng-deepsą przestarzałe, sugeruję zapoznanie się z tą odpowiedzią stackoverflow.com/a/49308475/2275011 i komentarzami, aby uzyskać więcej szczegółów i rozwiązań.
Ferie

Odpowiedzi:


92

Zwykle /deep/ “shadow-piercing”można użyć kombinatora, aby wymusić obniżenie stylu child components. Ten selektor miał alias >>>, a teraz ma inny o nazwie :: ng-deep.

ponieważ /deep/ combinatorzostał uznany za przestarzały, zaleca się użycie::ng-deep

Na przykład:

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

i css

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

zostanie zastosowany do komponentów potomnych


Czy to obsługuje IE11?
Jeyabalan Thavamani

2
Angular analizuje to - więc nie musisz się martwić o kompatybilność.
Simon_Weaver,

czy dotyczy to tylko komponentów potomnych? jak pamiętam i jak widzę w innym komentarzu, dotyczy to również elementów dom poza komponentem.
yaya

Mogę potwierdzić, że obsługuje również komponenty macierzyste ... Po prostu miałem obudowę i denerwowało mnie to.
Shadoweb

1
Świetnie, działało idealnie.
Alfredo Zamudio

70

STOSOWANIE

::ng-deep, >>>A /deep/wyłączenie enkapsulacji widok konkretnych reguł CSS, innymi słowy, daje dostęp do elementów DOM, które nie znajdują się w kodzie HTML składnika. Na przykład, jeśli używasz Angular Material (lub dowolnej innej biblioteki takiej jak ta), niektóre wygenerowane elementy znajdują się poza obszarem twojego komponentu (na przykład okno dialogowe ) i nie możesz uzyskać dostępu do tych elementów bezpośrednio lub za pomocą zwykłego CSS sposób. Jeśli chcesz zmienić style tych elementów, możesz użyć jednej z tych trzech rzeczy, na przykład:

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

Na razie zespół Angular zaleca wykonywanie „głębokich” manipulacji tylko przy użyciu hermetyzacji widoku EMULOWANEGO .

DEZAPROBATA

„głębokie” manipulacje również są przestarzałe , ALE na razie nadal działa, ponieważ Angular obsługuje przetwarzanie wstępne (nie spiesz się, aby odmówić ::ng-deepdzisiaj, zapoznaj się z praktykami wycofywania najpierw ).

W każdym razie, zanim pójdziesz w ten sposób, polecam przyjrzeć się wyłączaniu podejścia hermetyzacji widoku (co też nie jest idealne, pozwala stylom przeniknąć do innych komponentów), ale w niektórych przypadkach jest to lepszy sposób. Jeśli zdecydowałeś się wyłączyć hermetyzację widoku, zdecydowanie zaleca się użycie określonych klas, aby uniknąć przecinania się reguł CSS, a na koniec uniknąć bałaganu w arkuszach stylów. Naprawdę łatwo jest wyłączyć bezpośrednio w .tspliku komponentu :

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

Więcej informacji na temat hermetyzacji widoku można znaleźć w tym artykule.


3
Wyłączenie hermetyzacji widoku powoduje zastosowanie całego kodu CSS w komponencie na całym świecie.
Vedran,

16
Nie używaj ViewEncapsulation.None! Spowoduje wiele szkód, umożliwiając przenikanie tych stylów do innych elementów.
Alex Klaus

1
@AlexKlaus, zgadzam się, dlatego w odpowiedzi wspomniałem, że to nie jest idealne. Właściwie użyłem go tylko raz, aby zastosować wspólne, powtarzalne style do komponentów Angular Material. Jeśli spróbujesz wyłączyć hermetyzację, prawdopodobnie w pewnym momencie pojawi się bałagan. Dobrze jest wiedzieć o tej opcji, ale nie używaj jej, jeśli nie masz całkowitej pewności, że jest to potrzebne.
Commercial Suicide

29

Chciałbym podkreślić znaczenie ograniczenia ::ng-deeptylko dzieci składnika poprzez wymaganie, aby rodzic był hermetyzowaną klasą css.

Aby to zadziałało, ważne jest, aby użyć ::ng-deeppo rodzicu, a nie wcześniej, w przeciwnym razie będzie to miało zastosowanie do wszystkich klas o tej samej nazwie w momencie ładowania składnika.

CSS komponentu:

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

Szablon komponentu:

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

Wynikowy (wygenerowany przez Angular) CSS:

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

EDYTOWAĆ:

Możesz osiągnąć to samo zachowanie, używając :hostsłowa kluczowego zamiast tworzenia nowej klasy CSS.

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

5
stary, twoja odpowiedź my-component ::ng-deep...uratowała mi dzień. Spędziłem cały dzień próbując zastosować styl dla mojego komponentu za pomocą ng-deep i nadpisałem wszystkie moje komponenty z całej mojej aplikacji.
Cristiano Bombazar

2
Warto zauważyć: „Aby określić zakres określonego stylu do bieżącego składnika i wszystkich jego potomków [ale nie globalnie], pamiętaj o dołączeniu selektora: host przed :: ng-deep”. Od: angular.io/guide/component-styles
StvnBrkdll

1
@CristianoBombazar - to samo zachowanie uzyskasz ze :hostsłowem kluczowym - dodano notatkę do odpowiedzi dla jasności.
Vedran

23

Upewnij się, że nie przegapisz wyjaśnienia, :host-contextktóre znajduje się bezpośrednio powyżej ::ng-deepw przewodniku kątowym: https://angular.io/guide/component-styles . Zastrzeżenie: przegapiłem to do tej pory i żałuję, że nie widziałem tego wcześniej.

::ng-deep jest często konieczne, gdy nie napisałeś komponentu i nie masz dostępu do jego źródła, ale :host-context może być bardzo przydatną opcją, gdy to zrobisz.

Na przykład mam czarny <h1>nagłówek wewnątrz zaprojektowanego przeze mnie komponentu i chcę mieć możliwość zmiany go na biały, gdy jest wyświetlany na ciemnym tle tematycznym.

Jeśli nie miałem dostępu do źródła, być może będę musiał to zrobić w css dla rodzica:

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

Ale zamiast tego :host-contextmożesz to zrobić wewnątrz komponentu.

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

Spowoduje to wyszukanie dowolnego miejsca w łańcuchu komponentów .theme-darki zastosowanie CSS do h1, jeśli zostanie znaleziony. To dobra alternatywa dla zbytniego polegania::ng-deep która choć często jest konieczna, jest rodzaju anty-wzorca.

W tym przypadku &jest zastępowany przezh1 (tak działa sass / scss), więc możesz zdefiniować swój „normalny” i tematyczny / alternatywny css tuż obok siebie, co jest bardzo przydatne.

Uważaj, aby uzyskać prawidłową liczbę plików :. Bo ::ng-deepjest dwóch i :host-contexttylko jeden.


Możesz również użyć, :host(.theme-dark)jeśli nie chcesz dziedziczyć theme-darkz żadnych komponentów nadrzędnych. Będzie to całkowicie zależało od projektu CSS Twojej witryny. Również atrybuty mogą być bardzo przydatne i można je łączyć w wyrafinowany sposób w samym CSS:host([theme='dark']:not([dayofweek='tuesday'))
Simon_Weaver

Zauważ również, że jest to zgodne z normalnymi regułami css, więc jeśli masz komponent, jak opisano powyżej (z css kontekstem hosta) wewnątrz kontenera, który ma .theme-lightklasę, to z kolei jest zagnieżdżona w kontenerze, w .theme-darkktórym nadal pobierze theme-darki zastosuje css. Ale jest to świetne rozwiązanie dla klas typu „modernizr” lub jeśli masz motyw ustawiony globalnie i tylko raz.
Simon_Weaver,

Czy mogę użyć: host-context zamiast :: ng-deep?
eddy

@eddy Jestem teraz zbyt śpiący, aby w pełni to przemyśleć, ale kontekst hosta jest prawie jak ng-deep, ale przechodzenie w górę drzewa DOM zamiast w dół. Więc to absolutnie nie jest równoważne, ale możesz
Simon_Weaver

2

Tylko aktualizacja:

Należy użyć ::ng-deepzamiast tego, /deep/który wydaje się być przestarzały.

Według dokumentacji:

Przerywający cień kombinator potomków jest przestarzały, a jego obsługa jest usuwana z głównych przeglądarek i narzędzi. W związku z tym planujemy porzucić obsługę Angulara (dla wszystkich 3 z / deep /, >>> i :: ng-deep). Do tego czasu należy preferować :: ng-deep ze względu na szerszą kompatybilność z narzędziami.

Znajdziesz go tutaj


5
W tym tekście jest wyraźnie napisane, że :: ng-deep również jest przestarzałe: „planujemy porzucić obsługę Angulara (dla wszystkich 3 z / deep /, >>> i :: ng-deep)”.
adripanico

-2

Używaj :: ng-deep z rozwagą. Używałem go w całej mojej aplikacji, aby ustawić różne kolory paska narzędzi Material Design na różne kolory w całej aplikacji, tylko po to, aby stwierdzić, że podczas testowania aplikacji kolory pasków narzędzi nakładają się na siebie. Przekonaj się, że to dlatego, że te style stają się globalne, zobacz ten artykuł Oto działające rozwiązanie kodu, które nie przenika do innych komponentów.

<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');
  }

}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.