如何删除选定的列表元素,而不是仅删除top li标签

问题描述 投票:0回答:2

我正在尝试删除特定的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);
}
javascript dom
2个回答
0
投票

在我的评论中,我建议你听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>

0
投票

问题是你传递给removeItem的id周围缺少引号:

removeBtn.setAttribute("onClick", `removeItem(${idName})`);

这应该是:

removeBtn.setAttribute("onClick", `removeItem('${idName}')`);

Better pattern

更好的做法是绑定click处理程序而不依赖于代码的字符串评估,而无需创建动态id属性值:

removeBtn.addEventListener("click", () => removeItem(list));

然后函数removeItem应该期望节点本身,而不是id:

function removeItem(child) {
  child.parentNode.removeChild(child);
}

您可以删除以下代码:

var idName = "note" + note;
list.setAttribute("id", idName);
© www.soinside.com 2019 - 2024. All rights reserved.