Пользовательский тип элемента сообщает HTMLElement при загрузке в скрипт type = module? - PullRequest
1 голос
/ 20 мая 2019

Я работаю с пользовательскими элементами и заметил, что в одном случае мне не удалось получить доступ к свойствам экземпляра, как в var prop = myCustomElement.myPropery // undefined, где свойство определено в классе как, например, get myProperty() { blah }.

Я свел проблему к тому, что сообщается как в myCustomElement.constructor (и, таким образом, к типу прототипа / экземпляра), когда пользовательский элемент определен в сценарии type = "module" против типа модуля.

Вот очень простой пример:

var test = document.getElementById ( "test" );

console.log ( test.mood, test.constructor );
<script type="module">
const template = document.createElement ( "template" );

template.innerHTML = "<span>Hello!</span>";

window.customElements.define ( "test-case",

class TestCase extends window.HTMLElement {
    constructor () {
        super ();
        
        var frag = template.content.cloneNode ( true ),
            shadow = this.attachShadow( { mode: "open" } );
        
        shadow.appendChild ( frag );
    }
    
    get mood () {
        return "Happy!";
    }
} );
</script>
<test-case id="test"></test-case>

... и без типа модуля

var test = document.getElementById ( "test" );

console.log ( test.mood, test.constructor );
<script>
const template = document.createElement ( "template" );

template.innerHTML = "<span>Hello!</span>";

window.customElements.define ( "test-case",

class TestCase extends window.HTMLElement {
    constructor () {
        super ();
        
        var frag = template.content.cloneNode ( true ),
            shadow = this.attachShadow( { mode: "open" } );
        
        shadow.appendChild ( frag );
    }
    
    get mood () {
        return "Happy!";
    }
} );
</script>
<test-case id="test"></test-case>

Это кажется совершенно неправильным, это поведение является преднамеренным?

А также, предполагая необходимость использования модуля, например, для Определяя пользовательский элемент, который будет использоваться внутри более крупного компонента или библиотеки, существует ли прямой способ предотвратить скрытие модулем типа пользовательского элемента?

Примечание: я тестирую это из последней версии Chrome (74.0.3729.157) и не пробовал другие браузеры.

Ответы [ 2 ]

1 голос
/ 20 мая 2019

Вам нужно подождать, пока элемент не будет определен.

См. Реестр пользовательских элементов .when Defined ()

whenDefined () метод интерфейса CustomElementRegistry возвращает Promise, который разрешается, когда задан именованный элемент.

customElements.whenDefined('test-case').then(
  () => {
    const test = document.getElementById("test");
    console.log(test.mood, test.constructor);
  }
);
<script type="module">
const template = document.createElement ( "template" );

template.innerHTML = "<span>Hello!</span>";

window.customElements.define ( "test-case",

class TestCase extends window.HTMLElement {
    constructor () {
        super ();
        
        var frag = template.content.cloneNode ( true ),
            shadow = this.attachShadow( { mode: "open" } );
        
        shadow.appendChild ( frag );
    }
    
    get mood () {
        return "Happy!";
    }
} );
</script>
<test-case id="test"></test-case>
0 голосов
/ 29 мая 2019

Ваш немодульный скрипт выполняется перед модульным скриптом. Поэтому вам просто нужно подождать, пока элемент не будет определен, но вызвать customElements.whenDefined: https://devdocs.io/dom/customelementregistry/whendefined

Также нет причин использовать window при использовании customElements или HTMLElement.

customElements.whenDefined('test-case').then(
  () => {  
const test = document.getElementById ( "test" );
console.log ( test.mood, test.constructor );
  }
);
<script type="module">
const template = document.createElement ( "template" );
template.innerHTML = "<span>Hello!</span>";
customElements.define ( "test-case",
  class TestCase extends HTMLElement {
constructor () {
  super ();
  const frag = template.content.cloneNode ( true );
  const shadow = this.attachShadow( { mode: "open" } );
  shadow.appendChild ( frag );
}
    
get mood () {
  return "Happy!";
}
  }
);
</script>
<test-case id="test"></test-case>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...