如何使用拼接从 HTML 待办事项列表中删除 DOM 元素

how to remove DOM element from HTML to-do list using splice

我正在尝试实施拼接方法以从 JavaScript 待办事项列表中删除项目。使用我当前的代码,当单击删除按钮时,一个项目将从列表中清楚地删除。

但是,单击删除按钮也会将列表转换为带有默认逗号的简单数组。关于如何使用 splice 方法正确设置删除功能有什么建议吗?

非常感谢!

var array = [];

function add() {
  var task = document.getElementById("task").value;
  array.push(task);
  var text = document.createTextNode(task);
  var li = document.createElement("li");
  var btn = document.createElement("button");
  btn.appendChild(document.createTextNode("x"));
  btn.setAttribute("onclick", 'remove()');
  li.appendChild(text);
  li.appendChild(btn);
  document.getElementById("myUl").appendChild(li);
}

function remove() {
  array.splice(1, 1);
  document.getElementById("myUl").innerHTML = array;
}
<input id="task">
<button onclick="add()">add</button>
<ul id="myUl"></ul>

您混淆了 值数组 DOM 中的元素列表。您的数组包含任务的文本值列表:

var task = document.getElementById("task").value;
array.push(task);

这只是来自输入值的字符串列表,但它与您页面中的元素列表无关。

当您尝试删除任务时:

function remove() {
  array.splice(1, 1);
  document.getElementById("myUl").innerHTML = array;
}

您使用 array.splice(1,1),其中 according to the docs 表示:

  • 您正在更新阵列
  • 您要删除从索引 1 开始的 1 个元素

基本上每次调用 remove() 时都会删除数组中的第二项。绝对不是你想要的

此外,您将字符串数组设置为 div 的 innerHTML:

document.getElementById("myUl").innerHTML = array;

这实际上用字符串列表替换了 ul 的全部内容,这是您观察到的行为。 这里就是要从DOM中移除对应的元素。

如果您想同时存储一系列任务,您有多种选择。您可以保留一个包含任务列表的数组,这将是添加的任务的副本,您需要将此列表与 HTML 元素一起维护。 维护任务列表的两个副本并不稳健,因为您需要手动更新它们,因此从另一个列表派生一个列表会更安全:

  • 需要时,从 dom
  • 中的元素生成任务数组
  • 让你的函数更新你的数组,并从中生成你的 DOM 元素。

根据您的用例,一个选项可能比另一个更好,如果您愿意支付可维护性价格以换取性能,您甚至可能只想保留重复的数组。

这是一个工作示例,我在其中使用 DOM 元素来获取当前任务列表:

function getTasks() {
  return Array.from(document.querySelectorAll('li')).map(l => l.dataset.taskName);
}

function onAddTaskClick() {
 addTask(document.getElementById("task").value);
 console.log(getTasks());
}

function addTask(task) {
  const text = document.createTextNode(task);
  const li = document.createElement("li");
  li.dataset.taskName = task;
  const btn = document.createElement("button");
  btn.appendChild(document.createTextNode("x"));
  // Instead of maintaining an array of elements and using splice,
  // you can use a closure to add an event listener that will remove 
  // itself from the DOM.
  btn.addEventListener('click', () => {
    li.remove();
    console.log(getTasks());
  });
  li.appendChild(text);
  li.appendChild(btn);
  document.getElementById("myUl").appendChild(li);
}

addTask('sampleTask1');
addTask('sampleTask2');
addTask('sampleTask3');
console.log(getTasks());
<input id="task">
<button onclick="onAddTaskClick()">add</button>
<ul id="myUl"></ul>

我对代码做了一些修改:

  • 用于 const 未重新分配的任何变量。
  • 使用 addEventListener 而不是 onclick,这允许您使用闭包。
  • 使用 closure 而不是数组,这允许事件处理程序引用需要删除的 li
  • 由于您不需要数组,我已将其删除