您正在混淆一个 值 数组和 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 的引用。
- 由于您不需要该数组,我已将其删除