点击Project实例时如何渲染任务数组?Todo列表任务添加异常求助
修复Todo列表中任务无法添加到选中项目的问题
核心问题梳理
你的代码里任务没法正确关联到选中的项目,主要是这几个关键错误:
- 全局
project变量是个空的新Project实例,不是用户点击选中的项目,导致所有任务都加到了这个空实例里 renderTasks里错误地直接访问isEmpty方法引用,没加括号调用;同时遍历的是全局taskArr,不是当前项目的任务数组addTaskBtn函数完全没用到选中的selectedProj,反而用了全局空Project,而且调用renderTasks时传参错误
具体修复步骤
删掉多余的全局变量
直接移除全局的project和taskArr,这俩不仅没用,还会混淆逻辑,所有操作都基于选中的selectedProj来做。修正
renderTasks函数- 调用
isEmpty()(加括号)来判断项目是否为空 - 遍历当前项目的
tasksArray,而非全局taskArr - 增加未选中项目的提示,引导用户先选项目
- 调用
修正
addTaskBtn函数- 先检查有没有选中项目,没有就提示用户
- 用
selectedProj来添加任务,而不是全局空Project - 添加任务后重新渲染当前选中项目的任务列表
修复删除按钮的事件逻辑
原删除按钮的事件参数错误,直接通过闭包获取当前项目即可,还要阻止事件冒泡,避免点击删除时触发父元素的选中事件。
修正后的完整代码
JavaScript部分
//单个项目类 class Project { constructor(name) { this.name = name; this.tasksArr = []; } get nameOfProject() { return this.name; } get tasksArray() { return this.tasksArr; } isEmpty() { return this.tasksArr.length === 0; } addTasksToProject(name, dueDate) { let newTask = new Task(name, dueDate); this.tasksArr.push(newTask); return newTask; } } //项目组类 class Projects { constructor() { this.listOfProjects = [new Project("示例项目")]; } addProjectToList(name) { let p = new Project(name); this.listOfProjects.push(p); return p; } get allProjects() { return this.listOfProjects; } get numOfProjects() { return this.listOfProjects.length; } } //任务类 class Task { constructor(name, dueDate) { this.name = name; this.dueDate = dueDate; this.completed = false; } } //全局变量 let projects = new Projects(); let projArr = projects.allProjects; let projectId = 0; let selectedProj = null; //渲染任务列表 function renderTasks(currentProj) { const taskList = document.getElementById("task-list"); //未选中项目时的提示 if (!currentProj) { taskList.textContent = "请先选择一个项目来查看或添加任务"; return; } if (currentProj.isEmpty()) { taskList.textContent = "该项目目前没有任务,请在下方添加任务"; } else { taskList.textContent = ""; //遍历当前项目的任务数组 currentProj.tasksArray.forEach(task => { const newTaskDiv = document.createElement("div"); newTaskDiv.textContent = task.name; newTaskDiv.classList.add("task-item"); taskList.appendChild(newTaskDiv); }); } } //选中项目事件 function selectProject(e) { let currentProj = projArr[e.currentTarget.id]; selectedProj = currentProj; renderTasks(selectedProj); } //渲染项目列表 projArr.forEach(renderProjects); function renderProjects(project) { const newProjectDiv = document.createElement("div"); const dltBtn = document.createElement("button"); const projectDom = document.getElementById("project-list"); newProjectDiv.textContent = project.nameOfProject; dltBtn.textContent = "删除"; newProjectDiv.classList.add("project-item"); newProjectDiv.appendChild(dltBtn); projectDom.append(newProjectDiv); newProjectDiv.id = projectId; //修正删除按钮逻辑 dltBtn.addEventListener("click", (e) => { e.stopPropagation(); //阻止事件冒泡到父元素的选中事件 const projectIndex = projArr.indexOf(project); if (projectIndex !== -1) { projArr.splice(projectIndex, 1); newProjectDiv.remove(); resetIds(projectIndex); //如果删除的是当前选中项目,清空选中状态 if (selectedProj === project) { selectedProj = null; renderTasks(null); } } projectId -= 1; }); newProjectDiv.addEventListener("click", selectProject); projectId++; } //重置项目DOM的ID function resetIds(startIndex) { for (let i = startIndex; i < projArr.length; i++) { const element = document.getElementById(i + 1); if (element) { element.id = i; } } } //事件监听 const addBtn = document.getElementById("add"); const addTask = document.getElementById("addTask") addBtn.addEventListener("click", addProjectBtn); addTask.addEventListener("click", addTaskBtn) //添加项目按钮逻辑 function addProjectBtn() { let projName = prompt("请输入项目名称"); if (!projName) return; //取消输入则返回 let pushProj = projects.addProjectToList(projName); renderProjects(pushProj); } //添加任务按钮逻辑 function addTaskBtn() { if (!selectedProj) { alert("请先选择一个项目"); return; } let taskName = prompt("请输入任务名称"); if (!taskName) return; selectedProj.addTasksToProject(taskName); renderTasks(selectedProj); }
HTML部分
<button id="add">添加项目</button> <button id="addTask">添加任务</button> <div class="container"></div> <div id="project-list" class="project-list"></div> <div id="task-list"></div>
内容的提问来源于stack exchange,提问作者Roger Lopez
相关产品推荐
相关产品推荐

