You need to enable JavaScript to run this app. 为什么JS实现的待办事项列表会出现重复展示的待办条目?
优惠活动
大模型
产品
解决方案
定价
更多

为什么JS实现的待办事项列表会出现重复展示的待办条目?

问题成因
  • 待办列表渲染逻辑存在重复追加的缺陷:loadTodos函数执行时没有前置清空列表容器的既有内容,每次触发都会完整遍历当前todos数组,将所有数组项对应的DOM节点直接追加到#todoList容器中,不会移除容器内之前已经渲染过的旧节点。
    • 首次添加待办时,容器内没有留存任何旧渲染内容,追加生成的1条待办节点后,页面显示符合预期。
    • 第二次触发添加逻辑时,容器已经留存了第一次渲染的1条待办节点;此时todos数组已经存入2条待办数据,函数会全量遍历数组,把2条待办对应的节点再次追加到容器末尾,最终列表就会呈现「原有1条旧待办 + 重复追加的1条旧待办 + 新增的1条新待办」的重复展示效果,和描述的异常完全匹配。
  • 存在非法DOM嵌套问题:代码中先通过document.createElement('li')创建了li节点,又给该节点的innerHTML赋值了包裹<li>标签的字符串,会造成li标签层层嵌套的不符合HTML规范的结构。
修复方案

修改loadTodos函数,在遍历生成待办节点前先清空列表容器的旧节点,同时修正内容赋值逻辑,避免非法嵌套:

let form = document.getElementById('todoForm');
let input = document.getElementById('todoInput');
let btn = document.getElementById('btn');
let todos = [];

const loadTodos = () => {
  let parent = document.getElementById('todoList');
  // 清空容器内所有旧渲染节点,从根源上避免重复追加
  parent.innerHTML = '';
  todos.forEach(todo => {
    let newLi = document.createElement('li');
    // 直接设置节点文本内容,不再嵌套多余的li标签
    newLi.textContent = todo.text;
    parent.appendChild(newLi);
  })
}

btn.addEventListener('click', (e) => {
  e.preventDefault();
  let text = input.value;
  // 拦截空白输入,避免生成无意义的待办项
  if (!text.trim()) return;
  let todo = {
    id: todos.length + 1,
    text: text,
    complete: false,
  }
  todos.push(todo);
  input.value = ''; // 添加完成后自动清空输入框
  loadTodos();
})

window.onload = () => {
  loadTodos();
}

修复效果验证:调整后每次调用loadTodos,都会先基于当前todos数组的最新状态重建完整列表,不会遗留旧的DOM节点,重复展示的问题会直接解决。


内容的提问来源于stack exchange,提问作者Timo222

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.11.06 12:45:04