You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助:基于JavaScript类实现ToDo List的OOP代码问题

修复你的OOP风格ToDo List实现

先梳理你代码里的几个核心问题:

  1. 私有属性访问错误:List类里的#toDo是私有字段,你用this.toDo访问会报错,必须用this.#toDo。
  2. addTask方法逻辑错误:你连续调用了两次push,而且把push的返回值(数组新长度)传给了renderList,应该只push一次,然后把整个待办数组传过去。
  3. removeTask方法无效:filter不会修改原数组,只是返回新数组,你需要用splice或者重新赋值给this.#toDo。
  4. Render类元素未挂载:constructor里获取的input、btn、ul都是局部变量,其他方法拿不到,得挂载到实例上。
  5. 渲染逻辑不完整:renderList里创建了li,但没添加到ul里,也没给删除按钮绑定事件。
  6. 缺失添加任务的事件绑定:Add按钮没绑定点击事件,没法触发添加操作。

下面是修正后的完整代码:

修正后的JavaScript代码

class List {
  #toDo = [];
  constructor(render) {
    this.render = render;
    // 初始化渲染空列表
    this.render.renderList(this.#toDo);
    // 给Render类绑定删除回调
    this.render.onRemoveTask = (task) => this.removeTask(task);
  }

  addTask(task) {
    // 只添加一次任务
    this.#toDo.push(task);
    // 传入完整的待办数组进行渲染
    this.render.renderList(this.#toDo);
  }

  removeTask(task) {
    // 过滤掉要删除的任务,重新赋值给私有数组
    this.#toDo = this.#toDo.filter(item => item !== task);
    // 重新渲染列表
    this.render.renderList(this.#toDo);
  }
}

class Render {
  constructor(container) {
    this.container = container;
    // 把DOM元素挂载到实例上,方便后续方法访问
    this.inputEl = container.querySelector("input");
    this.addBtn = container.querySelector("button");
    this.taskUl = container.querySelector(".tasks");
    
    // 绑定添加任务的点击事件
    this.addBtn.addEventListener("click", () => this.handleAddTask());
  }

  // 存储删除回调的方法
  onRemoveTask = () => {};
  // 存储添加回调的方法
  onAddTask = () => {};

  handleAddTask() {
    const taskText = this.inputEl.value.trim();
    if (taskText) {
      // 调用List的addTask方法
      this.onAddTask(taskText);
      // 清空输入框
      this.inputEl.value = "";
    }
  }

  renderList(tasks) {
    // 先清空现有列表,避免重复渲染
    this.taskUl.innerHTML = "";
    
    tasks.forEach(task => {
      const li = document.createElement("li");
      li.innerHTML = `${task} <button class="delete-btn">Delete</button>`;
      // 给删除按钮绑定事件
      const deleteBtn = li.querySelector(".delete-btn");
      deleteBtn.addEventListener("click", () => this.onRemoveTask(task));
      // 将li添加到ul中
      this.taskUl.appendChild(li);
    });
  }
}

// 初始化实例
const render = new Render(document.querySelector("#to-do-container"));
const list = new List(render);
// 给Render绑定添加任务的回调
render.onAddTask = (task) => list.addTask(task);

修正后的HTML代码

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>ToDo List</title>
  <style>
    div {
      margin: 80px auto;
      text-align: center;
    }
    input {
      width: 20%;
    }
    li {
      list-style: none;
      margin: 8px 0;
    }
    .delete-btn {
      margin-left: 10px;
    }
  </style>
</head>
<body>
  <div id="to-do-container">
    <input type="text" placeholder="输入待办任务..." />
    <button>Add Task</button>
    <ul class="tasks"></ul>
  </div>

  <script>
    // 把上面的JavaScript代码放在这里即可
  </script>
</body>
</html>

关键改进说明:

  • 私有字段#toDo的正确访问方式
  • 修复了addTask和removeTask的逻辑错误
  • Render类中DOM元素的正确挂载与事件绑定
  • 渲染时先清空列表再重新生成,避免重复内容
  • 通过回调函数实现List和Render类之间的通信,解耦两个模块

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 01:13:14