英文:
Unable to manipulate element created by appendChild()
问题
我正在处理这个问题,但总是坑爹。我有一个JavaScript类,它克隆一个<template>
元素,然后附加到文档主体。然后我想操作那个新创建的元素...但它总是坚持说它是未定义的。
模板
<template id="js-modalTemplate">
<aside class="o--modal" style="display: none">
<button class="o-modal__close-button">
Close
</button>
<div><iframe class="js-video" src=""></iframe></div>
</aside>
</template>
ES模块
export default class Modal {
constructor() {
const template = document.getElementById('js-modalTemplate');
const modalTemplate = template.content.cloneNode(true);
this.modalElement = document.body.appendChild(modalTemplate);
console.log(this.modalElement);
this.modalElement.style.display = "block";
}
}
脚本元素
<script type="module">
import VideoModal from "{{ Vite::asset('resources/js/components/Modal.js') }}";
window.testModal = new Modal();
</script>
控制台输出的元素有时候是完整的,但有时候是空的(没有更改代码)...
空片段:
带内容的片段:
无论如何,我总是得到以下错误:
未捕获的TypeError:无法设置未定义的属性(设置'display')
并且元素始终出现在DOM中的预期位置。
我尝试过的事情
- 将脚本元素移动到
document.body
底部并添加defer
。 (这两者都不应该是必要的,因为它是ES模块,所以它会自动延迟加载。) - 将代码放在
window.onload
中,出于类似的原因
只是使用<template>
会导致这个问题,但我以前从未使用过它们,所以我不知道原因是什么!
英文:
I'm pulling my hair out on this one. I have a JavaScript class that clones a <template>
element and then is appended to the document body. I want to then manipulate that newly created element... but it always insists it's undefined.
Template
<template id="js-modalTemplate">
<aside class="o--modal" style="display: none">
<button class="o-modal__close-button">
Close
</button>
<div><iframe class="js-video" src=""></iframe></div>
</aside>
</template>
ES Module
export default class Modal {
constructor() {
const template = document.getElementById('js-modalTemplate');
const modalTemplate = template.content.cloneNode(true)
this.modalElement = document.body.appendChild(modalTemplate)
console.log(this.modalElement)
this.modalElement.style.display = "block"
}
}
Script element
<script type="module">
import VideoModal from "{{ Vite::asset('resources/js/components/Modal.js') }}"
window.testModal = new Modal()
</script>
The console.log output of the element sometimes appears in full, but sometimes it's empty (no changes to code)...
Empty fragment:
Fragment with content:
However I always get the following error, no matter what:
> Uncaught TypeError: Cannot set properties of undefined (setting 'display')
And the element always appears in the DOM at the expected place.
Things I've tried
- Moving the script element to the bottom of
document.body
and addingdefer
. (Neither of these things should be necessary because it's an ES Module anyway and so it automatically deferred.) - Placing the code within
window.onload
for similar reasons
There's just something about using a <template>
that causes this issue, but I've never used them before so I don't know what!
答案1
得分: 1
你可以在将其附加到 DOM 之前,通过 firstElementChild
从片段中获取顶级元素(<aside>
)。
this.modalElement = modalTemplate.firstElementChild;
document.body.appendChild(modalTemplate);
英文:
You could get the top level element (the <aside>
) from the fragment through firstElementChild
before appending it to the DOM.
this.modalElement = modalTemplate.firstElementChild;
document.body.appendChild(modalTemplate);
答案2
得分: 1
你的问题在于模板内容表示一个 DocumentFragment...
> 它被用作 Document 的轻量版本,用于存储由节点组成的文档结构的片段
换句话说,它是内容的容器,而不是内容本身。
如果你想操作任何特定的节点,比如 <aside>
,你需要在片段中定位它。
例如,使用 firstElementChild 属性
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
const template = document.getElementById("js-modalTemplate");
const content = template.content.cloneNode(true).firstElementChild;
console.log('style.display:', content.style.display);
<!-- language: lang-html -->
<template id="js-modalTemplate">
<aside class="o--modal" style="display: none">
<button class="o-modal__close-button">
Close
</button>
<div><iframe class="js-video" src=""></iframe></div>
</aside>
</template>
<!-- end snippet -->
英文:
Your issue is that the template content represents a DocumentFragment...
> It is used as a lightweight version of Document that stores a segment of a document structure comprised of nodes
That is, it is a container for the content, not the content itself.
If you want to operate on any particular node like the <aside>
, you need to locate it within the fragment.
For example, using the firstElementChild property
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
const template = document.getElementById("js-modalTemplate");
const content = template.content.cloneNode(true).firstElementChild;
console.log('style.display:', content.style.display);
<!-- language: lang-html -->
<template id="js-modalTemplate">
<aside class="o--modal" style="display: none">
<button class="o-modal__close-button">
Close
</button>
<div><iframe class="js-video" src=""></iframe></div>
</aside>
</template>
<!-- end snippet -->
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论