Расширить пользовательский элемент веб-компонентов v1

У меня есть собственный веб-компонент, <app-list> что я пытаюсь расширить в <calcs-list>,

// app-list.html

<script>
    window.customElements.define('app-list',

        class AppList extends HTMLElement {
            constructor() {
                super();
            }
        }

    );
</script>

В calcs-list.html я получил:

<link rel="import" href="app-list.html">
<script>

window.customElements.define('calcs-list',

    class CalcsList extends AppList {

        constructor() {
            super();
            console.log('CalcsList constructed');
        }

    }

);

</script>

Однако я получаю ошибку

Uncaught ReferenceError: AppList не определен в calcs-list.html:11

Линия 11 ссылок class CalcsList extends AppList {

Оба файла являются братьями и сестрами одной и той же папки. Я пытался использовать абсолютный путь при импорте app-list.html в calcs-list.html но получил тот же результат.

Я также попытался импортировать оба компонента в мой основной файл index.html:

//index.html
<link rel="import" href="/src/components/app-list.html">
<link rel="import" href="/src/components/calcs-list.html">

<app-list></app-list>
<calcs-list></calcs-list>

Но опыт тот же результат.

app-list Компонент работает в моем приложении без каких-либо проблем.

Я ломаю голову над этим, и поскольку веб-компоненты значительно новы, в Интернете не так много информации об устранении неполадок, особенно с веб-компонентами V1.

Спасибо!

2 ответа

Решение

Благодаря @Supersharp я переписал собственное объявление компонента как таковое:

// app-list.html    
<script>
    class AppList extends HTMLElement { ... }
    customElements.define('app-list', AppList);
</script>

А также calcs-list.html:

<script>
    class CalcsList extends AppList { ... }
    customElements.define('calcs-list', CalcsList);
</script>

Предупреждение: если вы объявляете тег внутри родительского элемента (расширяемого элемента) с id тогда это будет конфликтовать с вызовом расширенного элемента super(),

Например:

<template id="app-list"> 
    ... 
</template>

Чтобы обойти эту проблему, используйте строковый литерал JavaScript, на который ссылаются разработчики Google, и не используйте id совсем.

<script>

    let template = document.createElement('template');
    template.innerHTML = `
        <style> ... </style>
        <div> ... </div>
    `;

    class AppList extends HTMLElement {
        constructor() {
            super();
            let shadowRoot = this.attachShadow({mode: 'open'}).appendChild(template.content.cloneNode(true));
        }
    }

</script>

Это потому, что когда ты пишешь:

customElements.define('app-list',
    class AppList extends HTMLElement {}
);

класс AppList определяется только в объеме define() вызов. Вот почему он не виден при последующем использовании во втором файле импорта.

Вместо этого вы должны сначала определить класс (глобально), а затем использовать его в определении пользовательского элемента:

// app-list.html

<script>
    class AppList extends HTMLElement {
      constructor() {
        super();
      }
    }        
    window.customElements.define('app-list', AppList);
</script>
Другие вопросы по тегам