6

Ich habe ein einfaches Beispiel mit Webkomponenten mit zwei benutzerdefinierten Elementen (v1) erstellt, wobei eines in einem anderen verschachtelt ist. index.html:Verschachteltes Element (Webkomponente) kann seine Vorlage nicht abrufen

<!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:

Aber im toolbar.html document.currentScript ist das gleiche wie in der App -container.html und daher querySelector('#app-toolbar') kann keine Vorlage mit der ID app-toolbar finden. Wie man dieses Problem löst?

Beispiel getestet auf Chrome 55 (ohne Polyfill).

Antwort

13

document.currentScript enthält einen Verweis auf das Skript, das derzeit analysiert und ausgeführt wird. Daher ist es nicht mehr für Ihren Zweck gültig, wenn die Funktion constructor() aufgerufen wird (aus einem anderen Skript).

Statt shoud Sie seinen Wert in einer Variablen am Anfang des Skripts speichern, und verwenden Sie diese Variable im Konstruktor:

<script> 
    var currentScript = document.currentScript 
    customElements.define(...) 
    ... 
</script> 

Wenn Sie mehrere Skripte haben, sollten Sie verschiedene Namen verwenden.

Alternativ können Sie auch den ephemeren Wert in einem Verschluss kapseln:

(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); 

Hier ist der Wert document.currentScript.ownerDocument zum owner Argumente zugeordnet ist, die nach wie vor richtig definiert ist, wenn constructor() aufgerufen wird.

owner ist lokal definiert, so dass Sie den gleichen Namen im anderen Dokument verwenden können.

+0

Supersharp, Vielen Dank! Frohes neues Jahr! –

+0

Danke, du auch! – Supersharp

Verwandte Themen