简体   繁体   English

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

[英]Unable to add Event Listener on imported Element Node

I am fetching a list of posts from an API and displaying them on webpage.我正在从 API 获取帖子列表并将其显示在网页上。 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 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我想这与importNode方法有关,因为我用createElement做了类似的事情并且它们工作得很好

EDIT编辑

I did some little experimenting.我做了一些小实验。 The JSON post object returned by API also consisted of an id field. API 返回的 JSON post 对象也包含一个 id 字段。 So, I basically added that id to each button that was being created.因此,我基本上将该 id 添加到正在创建的每个按钮中。

Another thing is I used event delegation to remove() the li whose button is clicked.另一件事是我使用事件委托来删除()单击其按钮的li

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.这基本上证明了按钮标签肯定存在,因为我们能够查询 select 并设置它的 id。 Strangely, when consoled it shows null .奇怪的是,当安慰它显示null

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 .错误消息说明btnnull ,这意味着postEl.querySelector('button')返回null ,这意味着postEl内部没有button标签。

You will need to carefully look at the result of document.importNode(postTemplate.content, true) and see what it contains.您需要仔细查看document.importNode(postTemplate.content, true)的结果并查看它包含的内容。 You will see that it does not contain a button tag.您将看到它不包含button标签。 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.因此,要么未添加button ,在这种情况下您将需要调整importNode ,或者,按钮不是button标签,而是其他东西,例如<input type="button" value="foo">

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM