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

时间:2019-04-13 19:30:15

标签: javascript dom

我正在尝试删除特定的li元素,基于此元素单击了x按钮。目前,我有一个错误

“ bZMQWNZvyQeA:42未捕获的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);
}

2 个答案:

答案 0 :(得分:0)

问题是您传递给removeItem的ID周围缺少引号:

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

这应该是:

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

更好的模式

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

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

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

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

您可以删除以下代码:

var idName = "note" + note;
list.setAttribute("id", idName);

答案 1 :(得分: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>