无法操作由appendChild()创建的元素。

huangapple go评论72阅读模式
英文:

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>

控制台输出的元素有时候是完整的,但有时候是空的(没有更改代码)...

空片段:

无法操作由appendChild()创建的元素。

带内容的片段:

无法操作由appendChild()创建的元素。

无论如何,我总是得到以下错误:

未捕获的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 &lt;template&gt; 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

&lt;template id=&quot;js-modalTemplate&quot;&gt;
    &lt;aside class=&quot;o--modal&quot; style=&quot;display: none&quot;&gt;
        &lt;button class=&quot;o-modal__close-button&quot;&gt;
            Close
        &lt;/button&gt;
        &lt;div&gt;&lt;iframe class=&quot;js-video&quot; src=&quot;&quot;&gt;&lt;/iframe&gt;&lt;/div&gt;
    &lt;/aside&gt;
&lt;/template&gt;

ES Module

export default class Modal {
  constructor() {
    const template = document.getElementById(&#39;js-modalTemplate&#39;);
    const modalTemplate = template.content.cloneNode(true)

    this.modalElement = document.body.appendChild(modalTemplate)

    console.log(this.modalElement)

    this.modalElement.style.display = &quot;block&quot;
  }
}

Script element

&lt;script type=&quot;module&quot;&gt;
   import VideoModal from &quot;{{ Vite::asset(&#39;resources/js/components/Modal.js&#39;) }}&quot;

   window.testModal = new Modal()
&lt;/script&gt;

The console.log output of the element sometimes appears in full, but sometimes it's empty (no changes to code)...

Empty fragment:

无法操作由appendChild()创建的元素。

Fragment with content:

无法操作由appendChild()创建的元素。

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 adding defer. (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 &lt;template&gt; that causes this issue, but I've never used them before so I don't know what!

答案1

得分: 1

你可以在将其附加到 DOM 之前,通过 firstElementChild 从片段中获取顶级元素(&lt;aside&gt;)。

this.modalElement = modalTemplate.firstElementChild;
document.body.appendChild(modalTemplate);
英文:

You could get the top level element (the &lt;aside&gt;) from the fragment through firstElementChild before appending it to the DOM.

this.modalElement = modalTemplate.firstElementChild;
document.body.appendChild(modalTemplate);

答案2

得分: 1

你的问题在于模板内容表示一个 DocumentFragment...

> 它被用作 Document 的轻量版本,用于存储由节点组成的文档结构的片段

换句话说,它是内容的容器,而不是内容本身。

如果你想操作任何特定的节点,比如 &lt;aside&gt;,你需要在片段中定位它。

例如,使用 firstElementChild 属性

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

const template = document.getElementById(&quot;js-modalTemplate&quot;);

const content = template.content.cloneNode(true).firstElementChild;
console.log(&#39;style.display:&#39;, content.style.display);

<!-- language: lang-html -->

&lt;template id=&quot;js-modalTemplate&quot;&gt;
    &lt;aside class=&quot;o--modal&quot; style=&quot;display: none&quot;&gt;
        &lt;button class=&quot;o-modal__close-button&quot;&gt;
            Close
        &lt;/button&gt;
        &lt;div&gt;&lt;iframe class=&quot;js-video&quot; src=&quot;&quot;&gt;&lt;/iframe&gt;&lt;/div&gt;
    &lt;/aside&gt;
&lt;/template&gt;

<!-- 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 &lt;aside&gt;, 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(&quot;js-modalTemplate&quot;);

const content = template.content.cloneNode(true).firstElementChild;
console.log(&#39;style.display:&#39;, content.style.display);

<!-- language: lang-html -->

&lt;template id=&quot;js-modalTemplate&quot;&gt;
    &lt;aside class=&quot;o--modal&quot; style=&quot;display: none&quot;&gt;
        &lt;button class=&quot;o-modal__close-button&quot;&gt;
            Close
        &lt;/button&gt;
        &lt;div&gt;&lt;iframe class=&quot;js-video&quot; src=&quot;&quot;&gt;&lt;/iframe&gt;&lt;/div&gt;
    &lt;/aside&gt;
&lt;/template&gt;

<!-- end snippet -->

huangapple
  • 本文由 发表于 2023年5月29日 08:59:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/76354145.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定