Как динамически установить ViewEncapsulation для веб-компонента? - PullRequest
1 голос
/ 18 апреля 2019

Я пытаюсь инициализировать компонент с или без Shadow DOM на основе браузера (поскольку IE не поддерживает Shadow DOM).

Я проверяю, является ли это IE11, и устанавливаю инкапсуляцию на Emulated дляIE и ShadowDom для других браузеров.

const agent = window.navigator.userAgent;
const isIe11 = agent.indexOf('MSIE') === -1 && agent.indexOf('Trident') > 0;

@Component({
   selector: 'my-web-component',
   templateUrl: '...html',
   styleUrls: ['...scss'],
   encapsulation: isIe11 ? ViewEncapsulation.Emulated : ViewEncapsulation.ShadowDom
})
export class NavbarComponent implements OnInit { ... }

Значение isIe11 является правильным согласно возвращаемому значению проверки браузера, но инкапсуляция всегда заканчивается ViewEncapsulation.Emulated.

Я подтвердил это через инспектора DOM, потому что я не вижу #shadow-root в DOM.Вместо этого я вижу _ngcontent-c0, который подтверждает эмуляцию инкапсуляции.

1 Ответ

1 голос
/ 18 апреля 2019

Это невозможно в том виде, в каком вы его представляете, потому что angular компилирует ваш код в режиме AOT, а на этапе компиляции браузер явно не известен.

Я могу думать только об одном способе достижения этого. Вы должны скомпилировать одно и то же приложение дважды. Один раз для не ShadowDom совместимого браузера и тот, в котором это возможно.

Затем на вашем сервере вы обслуживаете все, что нужно, в зависимости от браузера, запрашивающего его. Я полагаю, вы также можете найти хакерский способ сделать это внутри index.html, который будет загружать правильные угловые библиотеки, основанные на текущем браузере. Для этого потребуется скрипт после ng build.

Вы можете обработать необходимую инкапсуляцию из файла вашей среды, поэтому, если у вас есть две разные среды для совместимых и несовместимых браузеров, вы можете добавить свойство внутри вашей среды:

// non shadow dom compatible env
export const environment = {
  // ...
  defaultEncapsulation: ViewEncapsulation.Emulated
}


// shadow dom compatible env
export const environment = {
  // ...
  defaultEncapsulation: ViewEncapsulation.ShadowDom
}

Если у вас есть эти два файла среды для ваших производственных сборок, вы можете отредактировать метод bootstrapModule внутри вашего main.ts, чтобы прочитать значение:

platformBrowserDynamic().bootstrapModule(AppModule, {
  defaultEncapsulation: environment.defaultEncapsulation
});
...