javascript - El elemento anidado(componente web) no puede obtener su plantilla
web-component shadow-dom (1)
document.currentScript
contiene una referencia al script que actualmente se analiza y ejecuta.
Por lo tanto, ya no es válido para su propósito cuando se llama a la función
constructor()
(desde otro script).
En su lugar, debe guardar su valor en una variable al comienzo del script y utilizar esta variable en el constructor:
<script>
var currentScript = document.currentScript
customElements.define( ... )
...
</script>
Si tiene varias secuencias de comandos, debe usar nombres distintos.
Alternativamente, puede encapsular el valor efímero en un cierre:
(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);
Aquí el valor
document.currentScript.ownerDocument
se asigna al argumento
owner
que todavía se define correctamente cuando se llama al
constructor()
.
owner
está definido localmente para que pueda usar el mismo nombre en el otro documento.
Hice un ejemplo simple usando componentes web con dos elementos personalizados (v1) donde uno está anidado en otro. 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>
app-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>
Pero en toolbar.html
document.currentScript
es el mismo que en app-container.html y, por
querySelector(''#app-toolbar'')
tanto,
querySelector(''#app-toolbar'')
no puede encontrar la plantilla con id
app-toolbar
.
¿Cómo resolver este problema?
Ejemplo probado en Chrome 55 (sin polyfill).