FontAwesome SVG в тени дома - PullRequest
1 голос
/ 04 мая 2020

Я пытаюсь использовать библиотеку шрифтов awsome js / svg в веб-компоненте, но значок не отображается. возможно ли это?

Я пытаюсь реализовать компонент angular в существующем проекте веб-форм без css и "прокачки" сценариев, какие-либо другие предложения о том, как это сделать? iframe не вариант.

    <html>
    <head>
        <script src="https://polygit.org/components/webcomponentsjs/webcomponents-loader.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.0/js/all.min.js" defer>
        </script>
        <script>
            customElements.define('my-holder', class extends HTMLElement {
                constructor() {
                    super();

                    console.log("constructor");
                    let shadowRoot = this.attachShadow({
                        mode: 'open'
                    });

                    const t = document.querySelector('#holder');
                    const instance = t.content.cloneNode(true);

                    shadowRoot.appendChild(instance);
                }

                connectedCallback() {
                    console.log("callback");
                }
            });
        </script>
    </head>

    <body>
        <div id="outside">
            light dom
            <div class="fa-4x">
                <span class="fa-layers fa-fw" style="background:MistyRose">
                    <i class="fas fa-circle" style="color:Tomato"></i>
                    <i class="fa-inverse fas fa-times" data-fa-transform="shrink-6"></i>
                </span>
            </div>
        </div>

        <template id="holder">
            <script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.0/js/all.min.js" defer></script>
            dark shadow dom
            <div class="fa-4x">
                <span class="fa-layers fa-fw" style="background:MistyRose">
                    <i class="fas fa-circle" style="color:Tomato"></i>
                    <i class="fa-inverse fas fa-times" data-fa-transform="shrink-6"></i>
                </span>
            </div>
        </template>

        <div id="inside">
            <my-holder></my-holder>
        </div>

    </body>
    </html>

1 Ответ

0 голосов
/ 04 мая 2020

Многие из этих библиотек oldskool используют document. для доступа к основному DOM.
Таким образом, они ничего не могут сделать с контентом в shadowDOM

Это означает, что ваша цель - не кровоточить сценарии выход невозможен.
Font-Awesome (сценарий и стили) должны быть загружены в основной DOM.

Если вы не хотите удалять стили за пределами shadowDOM, вы должны играть с помощью правила:

  • Значения Font-Awesome должны оставаться в главном DOM

  • lightDOM является (основным DOM) 'original' для shadowDOM содержимого со слотами

  • lightDOM оформляется основным DOM
    (или его контейнером shadowDOM, если сам элемент находится внутри другого shadowDOM )

  • с прорезями lightDOM остается в lightDOM , только отражается до <slot></slot>

  • Вы не хотите повторять определения значков FontAwesome в каждом lightDOM
    (вы также можете не тогда используйте пользовательских элементов)

    <span class="fa-4x fa-layers fa-fw">
      <i class="fas fa-circle"></i>
      <i class="fa-inverse fas fa-times" data-fa-transform="shrink-6"></i>
    </span>    
  • Пользовательский элемент может получить доступ ко всему DOM

Решение:

Напишите пользовательский элемент, который

  • создает свой собственный lightDOM
  • , который имеет слот <slot></slot> ( отражено! не перемещен! )
  • принимает конфигурацию из атрибутов
    <awesome-icon background="lightcoral" color="red"></awesome-icon>
    <awesome-icon background="lightgreen" color="green"></awesome-icon>
    <awesome-icon></awesome-icon>

JSFidlle: https://jsfiddle.net/CustomElementsExamples/1pmvasnj/

<script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.0/js/all.min.js" defer></script>
<script>
  customElements.define('awesome-icon', class extends HTMLElement {
    constructor() {
      super().attachShadow({mode: 'open'})
      .append(document.getElementById(this.nodeName).content.cloneNode(true));
    }
    connectedCallback() {
      let setProperty =
          (prop, value)=>this.shadowRoot.host.style.setProperty('--' + prop, value);
      setProperty('fa-background', this.getAttribute('background'));
      setProperty('fa-color', this.getAttribute('color'));
      // move icon HTML back to lightDOM so FontAwesome can style it
      this.innerHTML = this.shadowRoot.querySelector('#ICON').innerHTML;
    }
  });
</script>
<template id="AWESOME-ICON">
  <style>
    ::slotted(*) {
      /* lightDOM SPAN has higher Specificity, only way out is using !important */
      background: var(--fa-background,grey) !important;
      color: var(--fa-color,darkgrey) !important;
    }
  </style>
  <template id="ICON">
    <span class="fa-4x fa-layers fa-fw">
      <i class="fas fa-circle"></i>
      <i class="fa-inverse fas fa-times" data-fa-transform="shrink-6"></i>
    </span>    
  </template>
  <slot><!--lightDOM REFLECTED here--></slot>
</template>
<awesome-icon><!-- lightDOM CREATED here --></awesome-icon>
<awesome-icon background="lightcoral" color="red"></awesome-icon>
<awesome-icon background="lightgreen" color="green"></awesome-icon>
<style>
  span{
    background:lightblue; /* !important inside shadowDOM overrules these settings */
    color:red;
  }
</style>

НЕ с использованием shadowDOM и SLOT-ов

И, опираясь на свойства scoped CSS, код упрощается:

<script>
  customElements.define('awesome-icon', class extends HTMLElement {
    connectedCallback() {
      this.append(document.getElementById(this.nodeName).content.cloneNode(true));
      this.style.setProperty('--fa-background', this.getAttribute('background') );
      this.style.setProperty('--fa-color'     , this.getAttribute('color')      );
    }
  });
</script>

<template id="AWESOME-ICON">
  <span class="fa-4x fa-layers fa-fw">
     <i class="fas fa-circle"></i>
     <i class="fa-inverse fas fa-times" data-fa-transform="shrink-6"></i>
  </span>
</template>

<awesome-icon background="lightcoral" color="red"></awesome-icon>
<awesome-icon background="lightgreen" color="green"></awesome-icon>
<awesome-icon></awesome-icon>

<style>
  span {
    background: var(--fa-background);
    color:      var(--fa-color     );
  }
</style>
...