Як і де використовувати :: ng-deep?


90

Я новачок у Angular 4, тож хтось може пояснити, як і де використовувати ::ng-deepв Angular 4?

Насправді я хочу переписати деякі властивості CSS дочірніх компонентів з батьківських компонентів. Більше того, чи підтримується це на IE11?


Так /deep/і ::ng-deepобидва застаріли, я пропоную вам прийняти до цього радить спочатку відповідь stackoverflow.com/a/49308475/2275011 і коментарі для отримання більш детальної інформації та рішень.
Фері

Відповіді:


92

Зазвичай /deep/ “shadow-piercing”комбінатор можна використовувати для змушення стилю child components. Цей селектор мав псевдонім >>>, а тепер має ще один, який називається :: ng-deep.

оскільки /deep/ combinatorзастаріла, рекомендується використовувати::ng-deep

Наприклад:

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

і css

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

це буде застосовано до дочірніх компонентів


Це підтримка IE11?
Jeyabalan Thavamani,

2
Angular виконує його синтаксичний аналіз, тому вам не потрібно турбуватися про сумісність.
Simon_Weaver

це лише для дочірніх компонентів? як я пам’ятаю і як я бачу в іншому коментарі, це також для елементів dom за межами компонента.
yaya

Я можу підтвердити, що це також батьківські компоненти ... Просто був випадок і мене це дратувало.
Shadoweb

1
Чудово, це спрацювало чудово.
Альфредо Замудіо

70

ВИКОРИСТАННЯ

::ng-deep, >>>а також /deep/вимкнути інкапсуляцію подання для певних правил CSS, іншими словами, це дає вам доступ до елементів DOM, яких немає в HTML вашого компонента. Наприклад, якщо ви використовуєте Angular Material (або будь-яку іншу сторонню бібліотеку, подібну до цієї), деякі згенеровані елементи знаходяться за межами області вашого компонента (наприклад, діалогове вікно ), і ви не можете отримати доступ до цих елементів безпосередньо або за допомогою звичайного CSS шлях. Якщо ви хочете змінити стилі цих елементів, ви можете використовувати одну з цих трьох речей, наприклад:

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

На даний момент команда Angular рекомендує робити "глибокі" маніпуляції лише за допомогою ЕМУЛЬТОВАНОЇ інкапсуляції подання.

ЗНИЖЕННЯ

"глибокі" маніпуляції насправді теж застаріли , АЛЕ поки що вони все ще працюють, тому що Angular підтримує попередню обробку (не поспішайте відмовляти ::ng-deepсьогодні, спочатку погляньте на практики припинення ).

У будь-якому випадку, перед тим, як слідувати цим способом, я рекомендую вам поглянути на вимкнення підходу інкапсуляції подання (що теж не ідеально, це дозволяє вашим стилям просочуватися в інші компоненти), але в деяких випадках це кращий спосіб. Якщо ви вирішили вимкнути інкапсуляцію подання, настійно рекомендуємо використовувати певні класи, щоб уникнути перетину правил CSS, і нарешті, уникайте безладу у ваших таблицях стилів. Це дуже просто відключити прямо у .tsфайлі компонента :

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

Ви можете знайти більше інформації про інкапсуляцію подання в цій статті.


3
Вимкнення інкапсуляції подання застосовує весь CSS у вашому компоненті глобально.
Ведран

17
Не використовуйте ViewEncapsulation.None! Це завдасть великої шкоди, зробивши можливим просочування цих стилів до інших компонентів.
Алекс Клаус,

1
@AlexKlaus, погодьтеся, ось чому я згадав у відповіді, що це не ідеально. Власне, я використав його лише один раз, щоб застосувати спільно повторювані стилі до компонентів Angular Material. Якщо ви спробуєте вимкнути інкапсуляцію, можливо, в якийсь момент у вас вийде безлад. Добре знати про цей варіант, але не використовуйте його, поки ви не впевнені, що вам це потрібно.
Комерційне самогубство

29

Я б наголосив на важливості обмеження ::ng-deep лише дочірніми компонентами компонента, вимагаючи від батьків бути інкапсульованим класом css.

Щоб це працювало, важливо використовувати ::ng-deep after після батьківського, а не раніше, інакше це стосувалося б усіх класів з однаковим ім'ям у момент завантаження компонента.

Компонент css:

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

Шаблон компонента:

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

Результат (згенерований під кутом) css:

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

РЕДАГУВАТИ:

Ви можете досягти такої ж поведінки, використовуючи :hostключове слово замість створення нового класу css.

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

5
чоловіче, ваша відповідь my-component ::ng-deep...щойно врятувала мені день. Я витрачав цілий день, намагаючись застосувати стиль для мого компонента за допомогою ng-deep, і перекривав усі свої компоненти з усього мого додатка.
Кріштіану Бомбазар

2
Варто зазначити: "Для того, щоб вказаний стиль охопити поточним компонентом та всіма його нащадками [але не глобально], обов’язково включіть: селектор хосту перед :: ng-deep." Від: angular.io/guide/component-styles
StvnBrkdll

1
@CristianoBombazar - ви отримаєте однакову поведінку з :hostключовим словом - додав примітку до відповіді для ясності.
Ведран

23

Не забудьте пропустити пояснення, :host-contextяке знаходиться безпосередньо ::ng-deepв кутовому керівництві: https://angular.io/guide/component-styles . Застереження: Я пропустив це дотепер і хотів би побачити це раніше.

::ng-deep часто необхідний, коли ви не писали компонент і не маєте доступу до його джерела, але :host-context може бути дуже корисним варіантом, коли ви це робите.

Наприклад, у мене є чорний <h1>заголовок всередині компонента, який я спроектував, і я хочу можливість змінити його на білий, коли він відображається на темному тематичному фоні.

Якщо у мене не було доступу до джерела, можливо, мені доведеться зробити це в css для батьків:

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

Але замість цього :host-contextви можете зробити це всередині компонента.

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

Це буде шукати в будь-якому місці ланцюжка компонентів .theme-darkі застосовувати css до h1, якщо буде знайдено. Це хороша альтернатива занадто багато покладатися на те, ::ng-deepщо, хоча це часто і потрібно, є певним анти-шаблоном.

У цьому випадку &символ замінюється наh1 файл (саме так працює sass / scss), так що ви можете визначити свій "звичайний" та тематичний / альтернативний css поруч один з одним, що дуже зручно.

Будьте обережні, щоб отримати правильну кількість :. Бо ::ng-deepїх два і :host-contextлише один.


Ви також можете використовувати, :host(.theme-dark)якщо не хочете успадковувати theme-darkбудь-які батьківські компоненти. Це повністю залежатиме від дизайну css вашого сайту. Крім того, атрибути можуть бути дуже корисними і їх можна комбінувати вишукано лише в css:host([theme='dark']:not([dayofweek='tuesday'))
Simon_Weaver

Також зауважте, що це слідує звичайним правилам css, тому, якщо у вас є компонент, як описано вище (з css-контекстом хосту) всередині контейнера, який має .theme-lightклас, він, у свою чергу, вкладений всередину контейнера, .theme-darkвін все одно підніме theme-darkта застосує css. Але це прекрасне рішення для класів типу „модернізр”, або якщо у вас є тема, встановлена ​​глобально і лише один раз.
Simon_Weaver

Чи можу я використовувати: host-context замість :: ng-deep?
Едді

@eddy Я зараз занадто сонний, щоб повністю обміркувати це, але контекст хоста майже як ng-deep, але йде вгору по дереву DOM, а не вниз. Тож це абсолютно не рівнозначно, але ви могли б
Simon_Weaver

2

Просто оновлення:

Ви повинні використовувати ::ng-deepзамість /deep/якого, здається, застаріле.

За документацією:

Комбінатор нащадків, що пронизує тінь, не підтримується, а підтримка видаляється з основних браузерів та інструментів. Таким чином, ми плануємо відмовитись від підтримки в Angular (для всіх 3 з / deep /, >>> та :: ng-deep). До цього часу :: ng-deep слід віддавати перевагу для ширшої сумісності з інструментами.

Ви можете знайти його тут


5
У цьому тексті чітко сказано: :: ng-deep також застарілий: "ми плануємо відмовитись від підтримки в Angular (для всіх 3 з / deep /, >>> та :: ng-deep)".
adripanico

-2

Використовуйте :: ng-deep з обережністю. Я використовував його в усьому своєму додатку, щоб встановити колір панелі інструментів дизайну матеріалів на різні кольори в моєму додатку, лише щоб виявити, що коли програма тестувала кольори панелі інструментів, наступали один на одного. Приходьте, щоб з’ясувати, що це тому, що ці стилі стають глобальними, див. Цю статтю Ось робоче рішення коду, яке не проникає в інші компоненти.

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

}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.