Вложенный элемент (веб-компонент) не может получить свой шаблон
Я сделал простой пример, используя веб-компоненты с двумя пользовательскими элементами (v1), где один вложен в другой. index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Example</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="import" href="app-container.html">
</head>
<body>
<app-container></app-container>
</body>
</html>
Приложение-container.html:
<link rel="import" href="toolbar.html">
<template id="app-container">
<app-toolbar></app-toolbar>
</template>
<script>
customElements.define('app-container', class extends HTMLElement {
constructor() {
super();
let shadowRoot = this.attachShadow({ mode: 'open' });
const content = document.currentScript.ownerDocument.querySelector('#app-container').content;
shadowRoot.appendChild(content.cloneNode(true));
}
});
</script>
toolbar.html:
<template id="app-toolbar">
<p>Ok!</p>
</template>
<script>
customElements.define('app-toolbar', class extends HTMLElement {
constructor() {
super();
let shadowRoot = this.attachShadow({ mode: 'open' });
const content = document.currentScript.ownerDocument.querySelector('#app-toolbar').content;
shadowRoot.appendChild(content.cloneNode(true));
}
});
</script>
Но в toolbar.html document.currentScript
такой же, как в app-container.html и, следовательно, querySelector('#app-toolbar')
не могу найти шаблон с идентификатором app-toolbar
, Как решить эту проблему?
Пример проверен на Chrome 55 (без полизаполнения).
1 ответ
document.currentScript
содержит ссылку на скрипт, который в данный момент анализируется и выполняется. Поэтому это больше не действует для ваших целей, когда constructor()
функция вызывается (из другого скрипта).
Вместо этого вы должны сохранить его значение в переменной в начале скрипта и использовать эту переменную в конструкторе:
<script>
var currentScript = document.currentScript
customElements.define( ... )
...
</script>
Если у вас есть несколько сценариев, вы должны использовать разные имена.
Кроме того, вы можете инкапсулировать эфемерное значение в замыкании:
(function(owner) {
customElements.define('app-container', class extends HTMLElement {
constructor() {
super();
let shadowRoot = this.attachShadow({ mode: 'open' });
const content = owner.querySelector('#app-container').content;
shadowRoot.appendChild(content.cloneNode(true));
}
});
})(document.currentScript.ownerDocument);
Здесь значение document.currentScript.ownerDocument
назначен на owner
аргумент, который все еще определен правильно, когда constructor()
называется.
owner
определяется локально, поэтому вы можете использовать то же имя в другом документе.