В повседневной работе, когда мы определяем Component , мы должны учитывать его инкапсуляцию , то есть ожидаете ли вы, что стиль, определенный в этом компоненте, будет действовать только на этот компонент, или вы хотите, чтобы он действовал глобально. В Angular стили компонента могут быть инкапсулированы в хост-элемент компонента, чтобы они не влияли на остальную часть приложения. Декоратор компонентов предоставляет параметры инкапсуляции, которые можно использовать для управления применением инкапсуляции представления для каждого компонента. [Рекомендации по соответствующему руководству: «Учебное пособие по Angular»]
В Angular существует три режима инкапсуляции, а именно ViewEncapsulation.ShadowDom, ViewEncapsulation.Emulated и ViewEncapsulation.None.
экспортировать перечисление ViewEncapsulation { /** * Эмулирует собственное поведение инкапсуляции Shadow DOM, добавляя определенный атрибут в * хост-элемент компонента и применение одного и того же атрибута ко всем предоставленным селекторам CSS * через {@link Component#styles Styles} или {@link Component#styleUrls styleUrls}. * * Это опция по умолчанию. */ Эмулируемый = 0, /** * Не обеспечивает никакой инкапсуляции стилей CSS. Это означает, что все предоставленные стили * можно использовать {@link Component#styles style} или {@link Component#styleUrls styleUrls}. * к любому элементу HTML приложения независимо от его основного компонента. */ Нет = 2, /** * Использует собственный Shadow DOM API браузера для инкапсуляции стилей CSS, то есть создает * ShadowRoot для хост-элемента компонента, который затем используется для инкапсуляции * все стили компонента. */ ТеньДом=3 }
Если не указано, значение получается из CompilerOptions. Параметр компилятора по умолчанию — ViewEncapsulation.Emulated.
Если для политики установлено значение ViewEncapsulation.Emulated, а компонент не указывает стили или styleUrls, он автоматически переключится на ViewEncapsulation.None.
Вы выяснили, почему в типе перечисления нет единицы ? Подробнее об этом позже.
Оставив в стороне инкапсуляцию ShadowDom в Angular, давайте сначала посмотрим, что такое ShadowDOM.
Теневой DOM позволяет прикрепить скрытое дерево DOM к обычному дереву DOM — оно начинается с теневого корневого узла. Ниже этого корневого узла может быть любой элемент, как и обычный элемент DOM.
Здесь есть некоторые термины, специфичные для Shadow DOM, которые нам необходимо понять:
Вы можете манипулировать теневым DOM так же, как и обычным DOM, например, добавляя дочерние узлы, устанавливая свойства и добавляя к узлу собственный стиль (например, через свойство element.style) или добавляя стили ко всему узлу. Теневой DOM (например, добавление стилей внутри элементов). Разница в том, что элементы внутри Shadow DOM никогда не будут влиять на элементы вне его (кроме :focus-within), что облегчает инкапсуляцию.
Давайте посмотрим на простой пример.
<!DOCTYPE html> <html> <голова> <мета-кодировка="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, Initial-scale=1.0"> <title>Теневой DOM</title> <стиль> охватывать{ цвет: зеленый; } </стиль> </голова> <тело> <span>Я root</span> <div id="app"></div> <скрипт> let app = document.querySelector('#app'); letshadow1 = app.attachShadow({режим: 'open'}); пусть style1 = document.createElement('style'); style1.appendChild(document.createTextNode("span{color: red;}")); тень1.appendChild(стиль1); let span1 = document.createElement('span'); span1.textContent = 'Я – span.'; тень1.appendChild(диапазон1); </скрипт> </тело> </html>
В приведенном выше примере определяются глобальный стиль диапазона и стиль диапазона в ShadowDOM. Видно, что они не зависят друг от друга.
После того, как вы поняли, что такое ShadowDOM, давайте взглянем на инкапсуляцию ShadowDOM в Angular.
Angular использует встроенный в браузер API Shadow DOM для переноса представления компонента в ShadowRoot (который служит главным элементом компонента) и изолированного применения предоставленных стилей. ViewEncapsulation.ShadowDom работает только в браузерах со встроенной поддержкой теневого DOM. Не все браузеры поддерживают его, поэтому ViewEncapsulation.Emulated является рекомендуемым режимом по умолчанию.
Например, в следующем примере используйте ViewEncapsulation.ShadowDom .
@Компонент({ селектор: 'пользователь-ребенок', templateUrl: 'UserChild.comComponent.html', стили: [` ч3{ цвет: красный; } `], инкапсуляция: ViewEncapsulation.ShadowDom }) класс экспорта UserChildComponent реализует OnInit { ... }
На работающей странице мы видим, что дочерний пользовательский компонент внутренне инкапсулирован в ShadowDOM, и стиль также инкапсулирован внутри, что не влияет на внешний стиль.
Angular изменяет селекторы CSS компонента так, чтобы они применялись только к представлению компонента и не влияли на другие элементы в приложении (эмулируя поведение Shadow DOM).
При использовании инкапсуляции макетного представления Angular предварительно обрабатывает все стили компонента, чтобы они применялись только к представлению компонента. В DOM работающего приложения Angular к элементу, содержащему компонент, использующий шаблон инкапсуляции макетного представления, прикреплены некоторые дополнительные атрибуты:
<hero-details _nghost-pmm-5> <h3 _ngcontent-pmm-5>Мистер Фантастик</h3> <команда героев _ngcontent-pmm-5 _nghost-pmm-6> <h4 _ngcontent-pmm-6>Команда</h4> </hero-team> </hero-details>
Таких атрибутов два:
Атрибут | Details_nghost |
---|---|
добавляется | к элементу, который обертывает представление компонента , который будет ShadowRoots в собственной оболочке Shadow DOM. Обычно это относится к элементу хоста компонента . |
_ngcontent | добавляется к дочерним элементам в представлениях компонентов , и эти атрибуты используются для сопоставления элементов с их соответствующими смоделированными ShadowRoots (основными элементами с соответствующими атрибутами _nghost). |
Точные значения этих свойств являются частной деталью реализации Angular. Они генерируются автоматически, и вам не следует ссылаться на них в коде приложения.
Они нацелены на сгенерированные стили компонентов, которые внедряются в части DOM:
[_nghost-pmm-5] { дисплей: блок; граница: 1 пиксель, сплошная черная; } h4[_ngcontent-pmm-6] { цвет фона: белый; граница: 1 пиксель, сплошная #777; }
Эти стили подвергаются постобработке, поэтому каждый селектор CSS дополняется соответствующим атрибутом _nghost или _ngcontent. Эти модифицированные селекторы гарантируют, что стили применяются к представлениям компонента изолированным и целенаправленным образом.
<p>ребенок работает!</p>
p{ цвет: зеленый; }
@Компонент({ селектор: 'app-child', templateUrl: './child.comComponent.html', styleUrls: ['./child.comComponent.scss'], инкапсуляция: ViewEncapsulation.Emulated }) класс экспорта ChildComponent реализует OnInit { ... }
Результатом настройки ViewEncapsulation.Emulated является отсутствие теневого DOM, но компонент инкапсулируется с помощью механизма упаковки стилей, предоставляемого Angular, поэтому на стиль компонента не влияют внешние воздействия. Хотя стиль по-прежнему применяется ко всему документу, Angular создает селектор [_ngcontent-oow-c11] для p. Видно, что стиль, который мы определили для компонента, был изменен Angular. Проще говоря, хотя это и глобальный стиль, он не повлияет на стили других компонентов благодаря автоматическому выбору. Если вы вручную добавите этот атрибут к другим элементам, стиль также будет применен к этому элементу.
Angular не применяет никакой формы инкапсуляции представления, что означает, что любые стили, указанные для компонента, фактически применяются глобально и могут повлиять на любой элемент HTML, присутствующий в приложении. По сути, этот шаблон аналогичен включению стилей в сам HTML.
родитель:
<p #caption>родитель работает!{{count}}</p> <p #caption>Первый: {{count}}</p> <span class="red-font">родитель</span> <app-child></app-child>
дочерний элемент:
<div style="border: 1px сплошной зеленый;"> <p>ребенок работает!</p> <span class="red-font">Дочерний</span> </div>
р{ цвет: зеленый; } .red-font { цвет: красный; }
@Компонент({ селектор: 'app-child', templateUrl: './child.comComponent.html', styleUrls: ['./child.comComponent.scss'], инкапсуляция: ViewEncapsulation.None }) класс экспорта ChildComponent реализует OnInit { ... }
Используйте ViewEncapsulation.Native в Angular2.
@Компонент({ ..., инкапсуляция: ViewEncapsulation.Native }) класс экспорта UserComponent {
Параметр ViewEncapsulation.Native приводит к использованию встроенной функции Shadow DOM. Angular будет отображать компонент в соответствии с форматом Shadow DOM, поддерживаемым браузером. Фактически это более поздний ViewEncapsulation.ShadowDom.
мы представили три метода инкапсуляции представления Angular и их соответствующие характеристики. В повседневной работе вам следует выбирать, какой метод инкапсуляции соответствует конкретным сценариям.