尝试在html导入中选择模板元素时获取null

时间:2017-08-17 04:15:39

标签: javascript html templates web-component html5-template

在我的应用中,我从A执行html导入到具有此功能的文件B。但它警告null。如果我直接在浏览器中打开B,它会警告模板HTML dom元素。这怎么可能发生,这相同的代码几乎来自谷歌自己的网络组件文档https://developers.google.com/web/fundamentals/architecture/building-components/customelements

<template id="x-foo-from-template">

</template>

<script>
    alert(document.querySelector('template'));
</script>

这是googles的例子:

<template id="x-foo-from-template">
  <style>
    p { color: orange; }
  </style>
  <p>I'm in Shadow DOM. My markup was stamped from a &lt;template&gt;.</p>
</template>

<script>
  customElements.define('x-foo-from-template', class extends HTMLElement {
    constructor() {
      super(); // always call super() first in the ctor.
      let shadowRoot = this.attachShadow({mode: 'open'});
      const t = document.querySelector('#x-foo-from-template');
      const instance = t.content.cloneNode(true);
      shadowRoot.appendChild(instance);
    }
    ...
  });
</script>

由于

1 个答案:

答案 0 :(得分:1)

为什么会发生这种情况?

导入包含scripttemplate的文件时需要考虑的两个因素:

  1. script将在导入时执行,而标记和其他资源需要明确地添加到主页面
    • 正如本article on imports所指出的那样(与Google文档相同的作者,上面链接):
  2.   

    导入链接并不意味着“ #include the content here ”。这意味着“解析器,取消获取此文档,以便以后可以使用”。 当脚本在导入时执行时,需要将样式表,标记和其他资源明确添加到主页面。

    1. 导入中的脚本在包含导入文档的窗口的上下文中执行。因此window.document指的是主页面文档,而不是模板文档。
    2. 这可以解释为什么您的脚本会提醒null

      回答以下评论中的问题:Google的上述示例与相关示例有何不同?

      在Google的示例中,对document.querySelector()的调用位于自定义元素的构造函数中,该元素在实例化时调用。因此,无论示例是否使用文件导入来定义自定义元素,在实例化元素之前都不会执行该代码。

      如何使其发挥作用:

      您可以创建对导入文档本身的引用,其中可以找到template

      // importDoc references this import's document
      var importDoc = document.currentScript.ownerDocument;
      
      alert(importDoc.querySelector('template'));
      

      或者,在将模板插入文档后,显然可以查询主文档。所以这也应该有效:

      var import = document.querySelector('link[rel="import"]').import;
      var template = import.querySelector('template');
      
      // Append template to main document
      document.head.appendChild(template);
      
      // Now you can query the main the document
      alert(document.querySelector('template'));