javascript web-component shadow-dom html-imports html5-template

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).