Элементы, объявленные в HTML после Custom Element, не отображаются - PullRequest
0 голосов
/ 11 ноября 2018

РЕАЛЬНОЕ БОЛЬШОЕ РЕДАКТИРОВАНИЕ: Привет, это редактирование № 3. Это здесь сверху, потому что, ну, это меняет фундаментальный вопрос этого поста.Короче говоря, я пытался поместить h1 s до и после одного элемента Custom.Ну ... только то, что я поставил до рендеринга.Итак, я предполагаю, что проблема в том, что элементы не отображаются после моих пользовательских элементов .Я не удаляю свои старые наблюдения, приведенные ниже, для целей записи, так как кто-то может столкнуться с этой проблемой и понять ее неправильно, как я.


Я немного пробую с Custom Elements v1в Chrome, но все не совсем правильно.

Собственный элемент, о котором идет речь - я называю его range-slider, - это просто набор 1 label, 1 input range и 1 input number, вместе взятых истиль, плюс number и range связаны друг с другом.

RangeSlider.js:

class RangeSlider extends HTMLElement {
    constructor() {
        super();
    }
    connectedCallback() {
        this.initShadowDom();
        this.flowInputToElem("field", "slider");
        this.flowInputToElem("slider", "field");
    }

    initShadowDom() {
        const shadowRoot = this.attachShadow({mode: "open"});
        shadowRoot.innerHTML = this.template;
    }
    flowInputToElem(inputId, elemId) {
        const shadowRoot = this.shadowRoot;
        const input = shadowRoot.getElementById(inputId);
        const elem = shadowRoot.getElementById(elemId);

        input.addEventListener("input", e => {
            const min = parseFloat(elem.min);
            const max = parseFloat(elem.max);
            const newVal = parseFloat(input.value);

            elem.value = newVal > max
                ? max
                : newVal < min
                    ? min
                    : newVal;
        });
    }

    get label() {
        return this.getAttribute("label") || "Range slider";
    }
    get min() {
        return this.getAttribute("min") || 0;
    }
    get max() {
        return this.getAttribute("max");
    }
    get value() {
        return this.getAttribute("value") || 0;
    }

    get template() {
        return `
            <style>
                @import url('style/appearance.css');
                @import url('style/color.css');
                @import url('style/size.css');
                @import url('style/position.css');
                @import url('components/rangeSlider/style/slider.css');
            </style>
            <form class="w-max arial">
                <label for="field">${this.label}:</label>
                <div class="flx flx-middle">
                    <input id="slider" type="range" min="${this.min}" max="${this.max}" value="${this.value}" class="slider 
                        w-big">
                    <input id="field" type="number" min="0" max="${Infinity}" value="${this.value}" class="mrg-none 
                        spin-none brd-none w-small bg-transp txt-center">
                </div>
            </form>
        `;
    }
}

window.customElements.define('range-slider', RangeSlider);

В моем понимании, с range-slider все в порядке.На самом деле, это работает;ну вроде.Если я добавлю более 1 range-slider в свой index.html, будет отображаться только первый.

index.html:

<!DOCTYPE html>
<html>
<head>
    <title>Pegada de carbono</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <link rel="stylesheet" type="text/css" href="style/position.css">
    <link rel="stylesheet" type="text/css" href="style/color.css">
    <link rel="stylesheet" type="text/css" href="style/size.css">

    <script src="components/rangeSlider/RangeSlider.js"></script>
</head>
<body class="pos-abs h-fill w-fill mrg-none pdg-none bg-white">
    <range-slider label="example 1" min="0" max="100" value="25"></range-slider>
    <range-slider label="example 2" min="0" max="100" value="45"></range-slider>
    <range-slider label="example 3" min="0" max="100" value="65"></range-slider>
</body>
</html>

Chrome: Only the first range-slider happened to render

Почему это так?

РЕДАКТИРОВАТЬ: Как ни странно, когда я добавляю элемент с помощью JavaScript, он отображается как ожидалось.

const rangeSlider = document.createElement("range-slider");
rangeSlider.label = "example 4";
rangeSlider.value = "65";
rangeSlider.max = "1000";
rangeSlider.min = "0";

document.body.appendChild(rangeSlider);

РЕДАКТИРОВАТЬ 2: Хорошо, я провел еще несколько тестов, и произошли более странные вещи: 1. если я добавлю 1 нативный элемент, то 1 range-slider (или наоборот), все будет хорошо;2. если я поставлю range-slider, нативный компонент, тогда другой range-slider, только первый range-slider рендеринг;(что означает, что даже собственный компонент не в порядке) 3. если я попытаюсь добавить range-slider s в другой пользовательский элемент, внешний пользовательский элемент будет в порядке, а также range-slider номер 1, но все остальные range-slider sнет.

1 Ответ

0 голосов
/ 12 ноября 2018

Я взял ваш код, немного его изменил и запустил в режиме сниппета здесь, на этой странице, и он работал нормально.

    class OtherEl  extends HTMLElement {
      constructor() {
        super();

        this.attachShadow({mode: "open"}).innerHTML = '<div style="background-color: yellow;padding:4px;"><range-slider label="inner slider" min="0" max="100" value="5"></range-slider></div>';
      }
    }

    window.customElements.define('other-el', OtherEl);

    class RangeSlider extends HTMLElement {
      constructor() {
        super();
        this.attachShadow({mode: "open"});
      }

      connectedCallback() {
        if (this.shadowRoot.childElementCount === 0) {
          this.shadowRoot.innerHTML = this.template;
          this.flowInputToElem("field", "slider");
          this.flowInputToElem("slider", "field");
        }
      }

      flowInputToElem(inputId, elemId) {
        const shadowRoot = this.shadowRoot;
        const input = shadowRoot.getElementById(inputId);
        const elem = shadowRoot.getElementById(elemId);

        input.addEventListener("input", e => {
          const min = elem.min;
          const max = elem.max;
          const newVal = input.value;
          elem.value = newVal > max ? max : newVal < min ? min : newVal;
        });
      }

      get label() {
        return this.getAttribute("label") || "Range slider";
      }
      get min() {
        return parseFloat(this.getAttribute("min") || '0');
      }
      get max() {
        return parseFloat(this.getAttribute("max") || '100');
      }
      get value() {
        return parseFloat(this.getAttribute("value") || '0');
      }

      get template() {
        return `
          <style>
            @import url('style/appearance.css');
            @import url('style/color.css');
            @import url('style/size.css');
            @import url('style/position.css');
            @import url('components/rangeSlider/style/slider.css');
          </style>
          <form class="w-max arial">
            <label for="field">${this.label}:</label>
            <div class="flx flx-middle">
              <input id="slider" type="range" min="${this.min}" max="${this.max}" value="${this.value}" class="slider w-big">
              <input id="field" type="number" min="0" max="${Infinity}" value="${this.value}" class="mrg-none spin-none brd-none w-small bg-transp txt-center">
              </div>
          </form>
        `;
      }
    }

    window.customElements.define('range-slider', RangeSlider);
  <h1>Before</h1>
  <range-slider label="example 1" min="0" max="100" value="25"></range-slider>
  <h2>After 1</h2>
  <range-slider label="example 2" min="0" max="100" value="45"></range-slider>
  <h2>After 2</h2>
  <range-slider label="example 3" min="0" max="100" value="65"></range-slider>
  <h2>After 3</h2>
  <other-el></other-el>
  <h2>After OtherEl</h2>

Затем я запустил его на своем сервере и увидел то, что вы видели. Показан только один элемент.

Only one showing

Но я заметил эту ошибку в инструментах разработки:

enter image description here

Поскольку у меня нет ваших CSS-файлов, мой CSS не загружается, и это приводит к сбою в коде веб-компонента.

Когда я закомментировал тег <style> в вашем шаблоне:

  get template() {
    return `
      <!-- <style>
        @import url('style/appearance.css');
        @import url('style/color.css');
        @import url('style/size.css');
        @import url('style/position.css');
        @import url('components/rangeSlider/style/slider.css');
      </style> -->
      <form class="w-max arial">
        <label for="field">${this.label}:</label>
        <div class="flx flx-middle">
          <input id="slider" type="range" min="${this.min}" max="${this.max}" value="${this.value}" class="slider w-big">
          <input id="field" type="number" min="0" max="${Infinity}" value="${this.value}" class="mrg-none spin-none brd-none w-small bg-transp txt-center">
          </div>
      </form>
    `;
  }
}

Затем появляются все 5, включая тот, что находится внутри моего другого элемента.

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...