我使用带有两个自定义元素(v1)的Web组件做了一个简单的例子,其中一个嵌套在另一个元素中.
index.html的:
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>
但是在toolbar.html中,document.currentScript与app-container.html中的相同,因此querySelector(‘#app-toolbar’)找不到具有id app-toolbar的模板.如何解决这个问题呢?
在Chrome 55(不含polyfill)上测试的示例.
解决方法
document.currentScript包含对当前正在解析和执行的脚本的引用.因此,当调用constructor()函数(从另一个脚本)时,它不再适用于您的目的.
相反,您应该在脚本开头的变量中保存其值,并在构造函数中使用此变量:
<script> var currentScript = document.currentScript customElements.define( ... ) ... </script>
如果您有多个脚本,则应使用不同的名称.
或者,您可以将ephemeral值封装在闭包中:
(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()时仍然正确定义.
所有者是本地定义的,因此您可以在其他文档中使用相同的名称.