[英]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
.错误消息说明
btn
为null
,这意味着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.