无法在导入元素节点上添加事件侦听器

发布于 2025-02-01 11:11:12 字数 2609 浏览 1 评论 0 原文

我正在获取来自API的帖子列表,并在网页上显示它们。现在,有一个与每个帖子关联的删除按钮,单击时应删除帖子。

index.html

    <template id="single-post">
      <li class="post-item">
        <h2></h2>
        <p></p>
        <button>DELETE</button>
      </li>
    </template>

    <ul class="posts"></ul>

app.js

  const listElement = document.querySelector('.posts');
  const postTemplate = document.getElementById('single-post');

  const listOfPosts = await sendHttpRequest(
    'GET',
    'https://jsonplaceholder.typicode.com/posts'
  );
  // listOfPosts is already in parsed format

  for (const post of listOfPosts) {
    const postEl = document.importNode(postTemplate.content, true);
    postEl.querySelector('h2').textContent = post.title.toUpperCase();
    postEl.querySelector('p').textContent = post.body;
    listElement.append(postEl);

    const btn = postEl.querySelector('button');
    console.log(btn, postEl);
    
    btn.addEventListener('click', () => {
      postEl.remove();
    });
  }

上面的代码仅获取第一篇文章并抛出

uck offult(在承诺中)TypeError:无法读取null的属性(读取'addeventListener') 在htmlbuttonelement.fetchposts

删除事件侦听器时,代码正常工作。

我想这与 exixpnode 方法有关,因为我已经使用进行了类似的操作CreateElement 他们的工作正常

编辑

我做了一些尝试。 API返回的JSON帖子对象也由ID字段组成。因此,我基本上将ID添加到正在创建的每个按钮中。

另一件事是我使用事件委托删除()单击其按钮的 li

而且非常令人惊讶的是它可以使用

  const listElement = document.querySelector('.posts');
  const postTemplate = document.getElementById('single-post');

  const listOfPosts = await sendHttpRequest(
    'GET',
    'https://jsonplaceholder.typicode.com/posts'
  );
  // listOfPosts is already in parsed format

  for (const post of listOfPosts) {
    const postEl = document.importNode(postTemplate.content, true);
    postEl.querySelector('h2').textContent = post.title.toUpperCase();
    postEl.querySelector('p').textContent = post.body;

    postEl.querySelector('button').id = post.id;   // HERE

    listElement.append(postEl);
}


// delete the li element
listElement.addEventListener('click', (event) => {
  if(event.target.tagName === 'BUTTON') {
    console.log(event.target);
    event.target.parentElement.remove();
  }
})

单击第一个列表帖子的删除按钮时,它会安装

<button id="1">DELETE</button>

并删除该项目。

该基础证明该按钮标签肯定在那里,因为我们能够查询选择并设置其ID。 奇怪的是,当安慰时,它显示 null

I am fetching a list of posts from an API and displaying them on webpage. Now, there is a Delete button associated with each post which when clicked should remove the post.

index.html

    <template id="single-post">
      <li class="post-item">
        <h2></h2>
        <p></p>
        <button>DELETE</button>
      </li>
    </template>

    <ul class="posts"></ul>

app.js

  const listElement = document.querySelector('.posts');
  const postTemplate = document.getElementById('single-post');

  const listOfPosts = await sendHttpRequest(
    'GET',
    'https://jsonplaceholder.typicode.com/posts'
  );
  // listOfPosts is already in parsed format

  for (const post of listOfPosts) {
    const postEl = document.importNode(postTemplate.content, true);
    postEl.querySelector('h2').textContent = post.title.toUpperCase();
    postEl.querySelector('p').textContent = post.body;
    listElement.append(postEl);

    const btn = postEl.querySelector('button');
    console.log(btn, postEl);
    
    btn.addEventListener('click', () => {
      postEl.remove();
    });
  }

The above code only fetches first post only and throws

Uncaught (in promise) TypeError: Cannot read properties of null (reading 'addEventListener')
at HTMLButtonElement.fetchPosts

When I remove the Event Listener, the code works fine.

I guess this is something to do with importNode method since I have done similar things with createElement and they worked fine

EDIT

I did some little experimenting. The JSON post object returned by API also consisted of an id field. So, I basically added that id to each button that was being created.

Another thing is I used event delegation to remove() the li whose button is clicked.

And very surprisingly It works

  const listElement = document.querySelector('.posts');
  const postTemplate = document.getElementById('single-post');

  const listOfPosts = await sendHttpRequest(
    'GET',
    'https://jsonplaceholder.typicode.com/posts'
  );
  // listOfPosts is already in parsed format

  for (const post of listOfPosts) {
    const postEl = document.importNode(postTemplate.content, true);
    postEl.querySelector('h2').textContent = post.title.toUpperCase();
    postEl.querySelector('p').textContent = post.body;

    postEl.querySelector('button').id = post.id;   // HERE

    listElement.append(postEl);
}


// delete the li element
listElement.addEventListener('click', (event) => {
  if(event.target.tagName === 'BUTTON') {
    console.log(event.target);
    event.target.parentElement.remove();
  }
})

when clicked on first list post's DELETE button, it consoles

<button id="1">DELETE</button>

and removes that item.

This bascially proves that the button tag is certainly there since we are able to query select and set its id.
Strangely, when consoled it shows null.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

杀手六號 2025-02-08 11:11:12

您的代码错误在此处:

btn.addEventListener('click', () => {
  postEl.remove();
});

错误消息阐明 BTN null ,这意味着 Postel.querySelector('button')返回 > null ,这意味着在 postel 中没有按钮标记。

您将需要仔细查看 document.importnode(posttemplate.content,true)的结果,然后查看其中包含的内容。您会看到它不包含按钮标签。因此,要么未添加按钮,在这种情况下,您需要调整 exixtnode ,或者,该按钮不是 button tag,但是,例如&lt; input type =“ button” value =“ foo”&gt; ,例如其他内容。

Your code errors out here:

btn.addEventListener('click', () => {
  postEl.remove();
});

The error message clarifies that btn is null, which means that postEl.querySelector('button') returned null, which means that there is no button tag inside postEl.

You will need to carefully look at the result of document.importNode(postTemplate.content, true) and see what it contains. You will see that it does not contain a button tag. So, either the button was not added, in which case you will need to adjust importNode, or, the button is not a button tag, but something else, like <input type="button" value="foo"> for example.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文