Разница между ViewEncapsulation.Native, ViewEncapsulation.None и ViewEncapsulation.Emulated

Может кто-нибудь объяснить, в чем разница между ViewEncapsulation.Native, ViewEncapsulation.None и ViewEncapsulation.Emulated в angular2.

Я пытался гуглить и читать некоторые статьи, но я не могу понять разницу.

Ниже у меня есть два компонента Home (home.ts), т.е. родительский компонент и MyComp (my-comp.ts). Я хочу определить стили в родительском, которые используются в дочернем компоненте.

Должен ли я использовать ViewEncapsulation.Native или ViewEncapsulation.None

home.ts

import {Component, ViewEncapsulation} from 'angular2/core';
import {MyComp} from './my-comp';
@Component({
  selector: 'home',  // <home></home>
  providers: [
  ],
  directives: [
    MyComp
  ],
  styles: [`
    .parent-comp-width {
       height: 300px;
       width: 300px;
       border: 1px solid black;
     }
    `],
  template:`
    <my-comp></my-comp>
    <div class="parent-comp-width"></div>
  `,
  encapsulation: ViewEncapsulation.Native
})
export class Home {
}

мой-comp.ts

import {Component} from 'angular2/core';

@Component({
  selector: 'my-comp',  // <home></home>
  template: `
  <div class="parent-comp-width">my-comp</div>
  `
})
export class MyComp {
}

3 ответа

Решение

обновить Если вы хотите, чтобы стили, которые добавляются в Parent применительно к Child вам нужно установить ViewEncapsulation.None в Child Компонент, поэтому он не предотвращает утечки стилей.

Emulated а также Native Это всего лишь два разных способа предотвратить утечку стилей из компонентов. None это единственный, который позволяет стилям пересекать границы компонентов.

оригинал

  • ViewEncapsulation.None просто без инкапсуляции

  • ViewEncapsulation.Emulated (в настоящее время используется по умолчанию в Angular2)
    добавляет атрибуты к тэгам компонентов и дочерним элементам и манипулирует CSS (добавляя атрибуты к селекторам), добавляемым на страницу, чтобы стили не сливались друг с другом - чтобы стили оставались на уровне компонентов, к которым они добавлены, даже при том, что стили все они добавляются в заголовок страницы при загрузке компонентов.

  • ViewEncapsulation.Native создает пользовательские элементы с теневым DOM, где собственная реализация браузеров обеспечивает определение стиля.
    Если браузер изначально не поддерживает теневой DOM, полифилы веб-компонентов необходимы для упрощения работы. Это похоже на ViewEncapsulation.Emulated но полифилы дороже, потому что они многозаполняют многие браузерные API, даже если большинство из них никогда не используются. углы главного Emulated эмуляция просто добавляет стоимость того, что она использует, и поэтому намного более эффективна для приложений Angular.

  • Родной: Использует родной Shadow DOM браузера. Проверьте поддержку браузера перед включением.
  • ShadowDom: использует встроенную в браузер версию Shadow DOM v1 для лучшей кросс-браузерной поддержки и является общим стандартом для всех браузеров. Проверьте разницу между Shadow DOM v0 и v1.
  • Эмулируемый: имитирует поведение Shadow DOM для определения области CSS для компонента и добавляет к голове.
  • None: ни Shadow DOM, ни пользовательская реализация, как глобальный CSS, который добавляется к голове

Angular использует ViewEncapsulation.Emulated в качестве режима инкапсуляции по умолчанию.

Возьмем для примера сценарий, в котором ComponentParent содержит ComponentChild. В этом примере мы обсуждаем различные сценарии инкапсуляции дляComponentParent.

import { ViewEncapsulation }  from '@angular/core';

@Component({
  selector: 'component-child',
  // templateUrl: './child.component.html',
  template: '<h1>Hello, child</h1>',
  // styleUrls: ['./child.component.scss'],
  style: '/* ... */'
})
export class ComponentParent {
  // ...
}

@Component({
  selector: 'component-parent',
  template: '<h1>Hello, parent</h1><component-child/>',
  style: 'h1{background-color:yellow}',
  encapsulation: ViewEncapsulation.Emulated // this is the default encapsulation for the angular component
})
export class ComponentParent {
  // ...
}

ViewEncapsulation имеет одно устаревшее значение:

  • Native- с использованием устаревшей Shadow DOM v0

и 3 действительных значения:

Никто

Это прозрачный режим, наиболее похожий на сценарий, в котором angular вообще не задействован.

И то и другое ComponentParent а также ComponentChild будет тег H1 с желтым фоном.

ShadowDom

Этот режим создает собственный корень теневой DOM вокруг компонента (в нашем случае:ComponentParent) содержание. Это защитит любой стиль (CSS/SASS), который мы объявляем внутри компонента, от утечки ВНЕСТИ компонента. Однако это будет применяться к дочерним компонентам, таким какComponentChild.

И то и другое ComponentParent а также ComponentChild будет иметь тег H1 с желтым фоном (аналогично None mode), но любой тег H1 за пределами ComponentParent НЕ будут затронуты.

Эмулированный

Короче говоря, это касается стилей, объявленных в ComponentParent ТОЛЬКО и ТОЛЬКО на ComponentParentcontent, но ИСКЛЮЧАЯ дочерние компоненты, такие какComponentChild. Другими словами, только на " чистых " HTML-элементах, но не на угловых веб-элементах (компонентах).

Только ComponentParent будет тег H1 с желтым фоном.

Дополнительное объяснение механизма эмуляции

В Emulated режим обычно прозрачен для нас, так как мы предпочитаем помещать наши глобальные стили (затрагивающие оба ComponentParent а также ComponentChild) который БУДЕТ проникать в оба None а также Emulated компоненты и их дочерние компоненты и элементы HTML.

Однако представьте себе ComponentChildявляется сторонним компонентом, и вы хотите его стилизовать. Вы НЕ сможете сделать это сEmulated режим применен к ComponentParentсоставная часть. Это связано сEmulated реализация:

КАЖДЫЙ HTML-элемент внутриComponentParent компонент будет украшен атрибутом имя компонента (без значения), например:

  • _nghost-c3: для контейнера компонентов
  • _ngcontent-c3: для содержимого компонента

Параллельно EACH (S)CSS-селектор в нашем компонентеComponentParent будет "инкапсулирован" (обусловлен) с тем же атрибутом имени компонента

.H1[_ngcontent-c3] {
  background-color:yellow;
}

В целом это означает, что только элементы ComponentParent будут затронуты, и наша цель украсить H1 стороннего компонента не удастся, поскольку у него нет (такого же, если есть) атрибута имени компонента (_ngcontent-c3)

Решения для сторонних компонентов:

  • Использовать ShadowDom если доступно
  • Отключить инкапсуляцию, использовать None
  • поместить стили в глобальный (S)CSS
  • имитировать эмуляцию для внутренних сторонних компонентов, украшая их элементы атрибутом имени компонента

из про-угловой книги:

Значения ViewEncapsulation:

  • Эмуляция: если указано это значение, Angular эмулирует Shadow DOM, записывая содержимое и стили для добавления атрибутов. Это поведение по умолчанию, если не указано значение инкапсуляции.

    Если вы осмотрите DOM с помощью инструментов разработчика браузера F12, вы увидите содержимое внешнего CSS-файла.

    ...
    <style>
    div[_ngcontent-c0] {
      background-color: lightcoral;
    }
    </style>
    ...

Селектор был изменен так, чтобы он соответствовал элементам div с атрибутом _ngcontent-c0 хотя вы можете увидеть другое имя в вашем браузере, так как имя атрибута динамически генерируется Angular.

Чтобы гарантировать, что CSS в элементе style влияет только на элементы HTML, управляемые компонентом, элементы в шаблоне модифицируются таким образом, чтобы они имели один и тот же динамически генерируемый атрибут, например так:

...
<div _ngcontent-c0="" class="form-group">
   <label _ngcontent-c0="">Name</label>
   <input _ngcontent-c0="" class="form-control ng-untouched ng-pristineng-invalid" 
        ng-reflect-name="name" name="name">
</div>
...
  • Собственный: если указано это значение, Angular использует функцию теневого DOM браузера. Это будет работать, только если в браузере реализован теневой DOM или если вы используете полифилл.
  • None: если указано это значение, Angular просто добавляет неизмененные стили CSS в раздел head документа HTML и позволяет браузеру выяснить, как применять стили с помощью обычных правил приоритета CSS.

Значения Native и None следует использовать с осторожностью. Браузерная поддержка функции теневого DOM настолько ограничена, что использование параметра Native целесообразно только в том случае, если вы используете библиотеку polyfill, которая обеспечивает совместимость с другими браузерами.

Опция None добавляет все стили, определенные компонентами, в раздел head документа HTML и позволяет браузеру выяснить, как их применять. Это дает преимущество работы во всех браузерах, но результаты непредсказуемы, и нет никакой изоляции между стилями, определенными различными компонентами.

Если кто-то подходит к этому вопросу, потому что он хочет стилизовать дочерние компоненты с помощью объявлений стилей родительского компонента, см. Этот ответ SO.

Однако, как указывает последний комментарий о принятом ответе, в Angular Docs говорится:

Пронзающий теневой комбайнатор устарел, и поддержка удаляется из основных браузеров и инструментов. Поэтому мы планируем отказаться от поддержки в Angular (для всех 3 of /deep/, >>> и::ng-deep). До тех пор:: ng-deep следует предпочитать для более широкой совместимости с инструментами.

Пожалуйста, обратитесь к приведенному ниже примеру, чтобы понять все три варианта:

encapsulation: ViewEncapsulation.Emulated
encapsulation: ViewEncapsulation.Native
encapsulation: ViewEncapsulation.None

Щелкните здесь, чтобы увидеть пример

Другие вопросы по тегам