首页 > 解决方案 > 如何将自定义元素与模板一起使用?

问题描述

我试图了解网络组件是如何工作的,所以我尝试编写一个在网络服务器上提供服务的小应用程序(在支持的 Chrome 上测试rel="import")

index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <link rel="import" href="my-app.html" />
  </head>
  <body>
    <my-app />
  </body>
</html>

my-app.html

<template id="template">
  <div>Welcome to my app!</div>
</template>

<script>
class MyApp extends HTMLElement {
  constructor() {
    super();
    const shadow = this.attachShadow({mode: "open"});
    const template = document.getElementById("template");
    const clone = document.importNode(template.content, true);
    shadow.appendChild(clone);
  }
}
customElements.define("my-app", MyApp);
</script>

但这似乎不起作用。该<my-app />标签根本没有在 DOM 中呈现,我在控制台上收到此错误:

未捕获的类型错误:无法读取 null 的属性“内容”

什么不能检索template节点?我究竟做错了什么?

我还想知道的是,是否允许我编写没有样板代码(doctype、head、body ......)的 HTML 文档,因为它是用来描述一个组件而不是一个完整的文档来按原样使用. HTML5 规范是否允许它和/或它是否被大多数浏览器正确解释?

感谢您的帮助。

标签: htmlweb-componentcustom-elementhtml-templates

解决方案


在模板内部时,不要使用document全局:

<template id="template">
  <div>Welcome to my app!</div>
</template>

<script>
class MyApp extends HTMLElement {
  constructor() {
    super();
    const shadow = this.attachShadow({mode: "open"});

    // while inside the imported HTML, `currentDocument` should be used instead of `document`
    const currentDocument = document.currentScript.ownerDocument;
    // notice the usage of `currentDocument`
    const template = currentDocument.querySelector('#template');

    const clone = document.importNode(template.content, true);
    shadow.appendChild(clone);
  }
}
customElements.define("my-app", MyApp);
</script>

Plunker 演示:https ://plnkr.co/edit/USvbddEDWCSotYrHic7n?p=preview



PS:Notes com 兼容性在这里,虽然我假设你知道 HTML 导入很快就会被弃用。


推荐阅读