【问题标题】:how to remove DOM element from HTML to-do list using splice如何使用拼接从 HTML 待办事项列表中删除 DOM 元素
【发布时间】:2019-04-14 18:37:50
【问题描述】:

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

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

非常感谢!

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>

【问题讨论】:

    标签: javascript html arrays list splice


    【解决方案1】:

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

    【讨论】:

    • 赞赏。还有一些方法可以使用拼接方法从用户输入数组中删除项目吗?意思是,用户在输入框中添加文本,点击“添加”,将输入推入数组,然后使用拼接方法移除输入的数组项?
    • 用有关如何保留一系列任务的文本更新了我的问题。我不建议您保留任务的副本,除非您以惊人的速度添加/删除任务,否则此解决方案应该可以工作。
    猜你喜欢
    • 2019-10-31
    • 1970-01-01
    • 2020-06-06
    • 2018-03-26
    • 2021-07-03
    • 2018-06-02
    • 2019-05-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多