在 html 导入中尝试 select 模板元素时获取空值
Getting null when trying to select a template element in an html import
在我的应用程序中,我从 A
执行 html 导入到包含此文件的 B
文件。但它警告为空。如果我直接在浏览器中打开 B
,它会提醒模板 HTML dom 元素。这怎么可能发生,同样的代码几乎来自 google 自己的 Web 组件文档 https://developers.google.com/web/fundamentals/architecture/building-components/customelements。
<template id="x-foo-from-template">
</template>
<script>
alert(document.querySelector('template'));
</script>
这是google的例子:
<template id="x-foo-from-template">
<style>
p { color: orange; }
</style>
<p>I'm in Shadow DOM. My markup was stamped from a <template>.</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>
谢谢
为什么会这样?
导入包含 script
和 template
的文件时要考虑的两个因素:
-
script
将在导入时执行,而标记和其他资源需要显式添加到主页
- 正如此 article on imports(Eric Bidelman 所指出的,他与 Google 问题中链接的文档是同一作者):
An import link doesn't mean "#include the content here". It means "parser, go off an fetch this document so I can use it later". While scripts execute at import time, stylesheets, markup, and other resources need to be added to the main page explicitly.
- 导入中的脚本在包含导入文档的window上下文中执行。所以
window.document
指的是主页文档,不是模板文档。
这应该可以解释为什么您的脚本会发出警报 null
。因为脚本是立即执行的,而模板还没有添加到主页面。
如何得到想要的结果:
您可以在可以找到 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'));
Google 的示例与所讨论的示例有何不同?
回复下面评论中的问题:
在 Google 的示例中,在自定义元素的构造函数中发现对 document.querySelector()
的调用。实例化元素时调用构造函数。因此,当此代码为 运行.
时,该元素已存在于主页面中
在我的应用程序中,我从 A
执行 html 导入到包含此文件的 B
文件。但它警告为空。如果我直接在浏览器中打开 B
,它会提醒模板 HTML dom 元素。这怎么可能发生,同样的代码几乎来自 google 自己的 Web 组件文档 https://developers.google.com/web/fundamentals/architecture/building-components/customelements。
<template id="x-foo-from-template">
</template>
<script>
alert(document.querySelector('template'));
</script>
这是google的例子:
<template id="x-foo-from-template">
<style>
p { color: orange; }
</style>
<p>I'm in Shadow DOM. My markup was stamped from a <template>.</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>
谢谢
为什么会这样?
导入包含 script
和 template
的文件时要考虑的两个因素:
-
script
将在导入时执行,而标记和其他资源需要显式添加到主页- 正如此 article on imports(Eric Bidelman 所指出的,他与 Google 问题中链接的文档是同一作者):
An import link doesn't mean "#include the content here". It means "parser, go off an fetch this document so I can use it later". While scripts execute at import time, stylesheets, markup, and other resources need to be added to the main page explicitly.
- 导入中的脚本在包含导入文档的window上下文中执行。所以
window.document
指的是主页文档,不是模板文档。
这应该可以解释为什么您的脚本会发出警报 null
。因为脚本是立即执行的,而模板还没有添加到主页面。
如何得到想要的结果:
您可以在可以找到 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'));
Google 的示例与所讨论的示例有何不同?
回复下面评论中的问题:
在 Google 的示例中,在自定义元素的构造函数中发现对 document.querySelector()
的调用。实例化元素时调用构造函数。因此,当此代码为 运行.