Как динамически установить ViewEncapsulation для веб-компонента?

Я пытаюсь инициализировать компонент с 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, который подтверждает, что инкапсуляция эмулируется.


person Taranjeet Singh    schedule 18.04.2019    source источник


Ответы (1)


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

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

Затем на своем сервере вы обслуживаете то, что необходимо, в зависимости от запроса браузера. Я полагаю, вы также можете найти хакерский способ сделать это внутри index.html, который загрузит правильные библиотеки angular на основе текущего браузера. Это потребуется после 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
});
person Poul Kruijt    schedule 18.04.2019