我正在尝试删除特定的li元素,基于哪个单击了x按钮。目前我有一个错误
“bZMQWNZvyQeA:42 Uncaught TypeError:无法在'Node'上执行'removeChild':参数1不是'Node'类型。”
我知道这可能意味着参数无效,但这对我没有任何意义。 Chrome开发工具显示onClick属性正确地表示removeItem,并传入idName作为参数。这怎么不行?
var note = 0;
function saveInfo() {
var idName = "note" + note;
//assign text from input box to var text, and store in local storage
var input = document.getElementById('input').value;
var text = localStorage.setItem(note, input);
var list = document.createElement("li");
var node = document.createTextNode(input);
var removeBtn = document.createElement("button");
list.setAttribute("id", idName);
removeBtn.setAttribute("onClick", `removeItem(${idName})`);
removeBtn.innerHTML = "X";
list.appendChild(node);
list.appendChild(removeBtn);
document.getElementById("output").appendChild(list);
note += 1;
}
function removeItem(name) {
var parent = document.getElementById("output");
var child = document.getElementById(name);
parent.removeChild(child);
}
在我的评论中,我建议你听removeBtn
点击事件冒泡。在这种情况下,您只需要从代码中删除onclick
属性赋值逻辑,而是将removeButton
赋予可识别的属性,例如类。让我们给它一类delete-button
:
var removeBtn = document.createElement("button");
removeBtn.classList.add('delete-button');
removeBtn.type = 'button';
removeBtn.innerHTML = 'X';
然后,您可以在#output
级别收听click事件,该事件保证在运行时出现。触发事件时,您只需检查事件目标是否具有可识别属性,例如在我们的案例中remove-button
类:
output.addEventListener('click', function(e) {
// GUARD: Do nothing if click event does not originate from delete button
if (!e.target.matches('.remove-button')) {
return;
}
// Delete parent node
e.target.closest('li').remove();
});
如果click事件不是来自删除按钮,我们只是return
而不做任何其他事情。否则,我们知道按钮已被点击,然后我们可以使用Element.closest()
,即.closest('li')
来检索最近的<li>
父节点并删除它。
如果你绝对必须支持IE11(反过来,不支持Element.closest()
),你也可以使用Node.parentNode
访问和删除<li>
元素,假设你的删除按钮是<li>
元素的直接子元素:
// Delete parent node
e.target.parentNode.remove();
请参阅下面的概念验证:
var rows = 10;
var output = document.getElementById('output');
for (var i = 0; i < rows; i++) {
var list = document.createElement('li');
var node = document.createTextNode('Testing. Row #' + i);
var removeBtn = document.createElement("button");
removeBtn.classList.add('remove-button');
removeBtn.type = 'button';
removeBtn.innerHTML = 'X';
list.appendChild(node);
list.appendChild(removeBtn);
output.appendChild(list);
}
output.addEventListener('click', function(e) {
// GUARD: Do nothing if click event does not originate from delete button
if (!e.target.matches('.remove-button')) {
return;
}
e.target.closest('li').remove();
});
<ul id="output"></ul>
问题是你传递给removeItem
的id周围缺少引号:
removeBtn.setAttribute("onClick", `removeItem(${idName})`);
这应该是:
removeBtn.setAttribute("onClick", `removeItem('${idName}')`);
更好的做法是绑定click处理程序而不依赖于代码的字符串评估,而无需创建动态id
属性值:
removeBtn.addEventListener("click", () => removeItem(list));
然后函数removeItem
应该期望节点本身,而不是id:
function removeItem(child) {
child.parentNode.removeChild(child);
}
您可以删除以下代码:
var idName = "note" + note;
list.setAttribute("id", idName);