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

Odin项目TodoList开发:如何获取激活项目索引以添加新任务?

待办事项列表项目问题:无法获取激活项目索引以添加任务

我正在开发Odin项目的待办事项列表(TodoList),已实现以下功能:

  • 创建新项目
  • 向项目添加任务
  • 侧边栏展示所有项目
  • 点击项目后在主区域渲染项目详情

页面效果:
点击项目前:
点击项目前的页面

点击项目后:
点击项目后的页面

目前遇到的问题:无法获取主区域当前显示的激活项目的索引,导致无法通过addTaskModal弹窗向该项目添加新任务。


相关代码

渲染项目到主区域的代码(renderMain.js)

import {
  addTaskModal
} from './addTaskModal.js';
import {
  myProjects
} from './myProjects.js';

const mainContent = document.querySelector('#main');

export default function renderMain(event) { // 从侧边栏渲染项目到主内容区

  mainContent.textContent = '';
  mainContent.appendChild(addTaskModal); // 输入新任务及优先级的弹窗

  let index = parseInt(event.target.id.split('-')[1]);

  const projectCard = document.createElement('div');
  projectCard.classList.add('card');

  const projectCardHeader = document.createElement('h3');
  projectCardHeader.classList.add('cardheader');
  projectCardHeader.textContent = myProjects[index].name
  projectCard.appendChild(projectCardHeader);

  const projectDue = document.createElement('div');
  projectDue.textContent = myProjects[index].due;
  projectDue.classList.add('date');
  projectCard.appendChild(projectDue);

  for (let i = 0; i < myProjects[index].tasks?.length; i++) {

    const tasks = document.createElement('div');
    const deleteBtn = document.createElement('button');
    deleteBtn.textContent = 'Delete Task';
    deleteBtn.addEventListener('click', () => {
      myProjects[index].tasks.splice(i, 1);
      localStorage.setItem('projects', JSON.stringify(myProjects));
      renderMain(event);
    })

    // 删除后更新数据,用相同key覆盖localStorage即可
    tasks.textContent = myProjects[index].tasks[i].name;
    tasks.classList.add('tasks');
    tasks.appendChild(deleteBtn);
    projectCard.appendChild(tasks);
  }
  const addTaskBtn = document.createElement('button');
  addTaskBtn.textContent = "Add Task";
  mainContent.appendChild(addTaskBtn);
  addTaskBtn.addEventListener('click', () => {
    addTaskModal.showModal();
  });
  mainContent.appendChild(addTaskBtn); // 此处重复添加了按钮,需注意
  mainContent.appendChild(projectCard)
}

myProjects数组代码(myProjects.js)

let myProjects = JSON.parse(localStorage.getItem('projects')) || [{
    name: "Go to supermarket",
    due: "12/2/25",
    tasks: [{
        name: "Buy apples",
        priority: "high"
      },
      {
        name: "Buy Eggs",
        priority: "medium"
      }
    ]
  },
  {
    name: "Clean the house",
    due: "13/2/25",
    tasks: [{
        name: "Sweep and mop the floor",
        priority: "high"
      },
      {
        name: "Do laundry",
        priority: "high"
      }
    ]
  }
];

export {
  myProjects
};

addTaskModal弹窗代码(addTaskModal.js)

import { myProjects } from "./myProjects.js";

const addTaskModal = document.createElement('dialog');

addTaskModal.classList.add('modal');

// 创建任务名称输入项
const newTask = document.createElement('div');
newTask.classList.add('modallabel');
newTask.textContent = "New Task :";
const newTaskInput = document.createElement('input');
newTaskInput.setAttribute('placeholder', 'Add New Task Here');
newTaskInput.setAttribute('id', 'newtaskinput');
newTaskInput.classList.add('inputbox');
newTask.appendChild(newTaskInput);

// 创建优先级选择项
const newPriority = document.createElement('div');
newPriority.textContent = "Priority: ";
newPriority.classList.add('prioritylabel');
const newPriorityInput = document.createElement('select');
newPriorityInput.setAttribute('id', 'newpriorityinput');

// 添加优先级选项
const selectHigh = document.createElement('option');
selectHigh.textContent = "High";
selectHigh.setAttribute('value', 'High')
newPriorityInput.appendChild(selectHigh);
const selectMedium = document.createElement('option');
selectMedium.textContent = "Medium";
newPriorityInput.appendChild(selectMedium);
const selectLow = document.createElement('option');
selectLow.textContent = "Low";
newPriorityInput.appendChild(selectLow);
newPriority.appendChild(newPriorityInput);

// 提交按钮
const submitNewTaskBtn = document.createElement('button');
submitNewTaskBtn.textContent = "Add Task";

addTaskModal.appendChild(newTask);
addTaskModal.appendChild(newPriority);
addTaskModal.appendChild(submitNewTaskBtn);

export { addTaskModal };
export { submitNewTaskBtn };

主文件代码(index.js)

import './styles.css';
import { myProjects } from './myProjects.js';
import renderMain from './renderMain.js';
import { addTaskModal } from './addTaskModal.js';

const mainContent = document.querySelector('#main');
const sideBar = document.querySelector('#sidebarproject');

function renderSidebar() {
    let sidebarHTML = '';
    myProjects.forEach((project, index) => {
        sidebarHTML += `<div class="projects" id="project-${index}">${project.name}</div>`
    })
    sideBar.innerHTML += sidebarHTML;
    const projects = document.querySelectorAll('.projects');
    projects.forEach(project => 
        project.addEventListener('click', renderMain)
    )
}

renderSidebar();

mainContent.appendChild(addTaskModal);

解决方案

核心问题是当前激活项目的索引未被持久存储,导致弹窗提交时无法定位目标项目。可通过以下步骤解决:

1. 存储当前激活的项目索引

修改renderMain.js,添加全局变量存储当前项目索引,也可将索引挂载到弹窗元素的自定义属性上:

// 文件顶部添加全局变量
let currentProjectIndex = -1;

export default function renderMain(event) {
  mainContent.textContent = '';
  mainContent.appendChild(addTaskModal);

  currentProjectIndex = parseInt(event.target.id.split('-')[1]);
  // 同时将索引存入弹窗的自定义属性,作为备选方案
  addTaskModal.dataset.projectIndex = currentProjectIndex;

  // 剩余原有代码...
}

// 导出变量供弹窗使用
export { currentProjectIndex };

2. 给弹窗提交按钮添加任务添加逻辑

修改addTaskModal.js,导入当前激活索引并绑定提交事件:

import { myProjects } from "./myProjects.js";
// 导入当前激活索引
import { currentProjectIndex } from './renderMain.js';

// ... 原有代码 ...

// 绑定提交按钮事件
submitNewTaskBtn.addEventListener('click', () => {
  const taskName = document.getElementById('newtaskinput').value.trim();
  const taskPriority = document.getElementById('newpriorityinput').value;

  if (!taskName) return; // 空任务不提交

  // 验证当前项目存在
  if (currentProjectIndex !== -1 && myProjects[currentProjectIndex]) {
    // 确保tasks数组已初始化
    if (!myProjects[currentProjectIndex].tasks) {
      myProjects[currentProjectIndex].tasks = [];
    }
    // 添加新任务
    myProjects[currentProjectIndex].tasks.push({
      name: taskName,
      priority: taskPriority.toLowerCase() // 和现有数据格式统一
    });
    // 更新本地存储
    localStorage.setItem('projects', JSON.stringify(myProjects));
    // 关闭弹窗并清空输入
    addTaskModal.close();
    document.getElementById('newtaskinput').value = '';
    // 重新渲染当前项目
    const activeProject = document.querySelector(`#project-${currentProjectIndex}`);
    if (activeProject) activeProject.click();
  }
});

// ... 原有导出代码 ...

3. 修复重复添加按钮问题

删除renderMain.js中重复的按钮添加代码:

// 移除此行重复代码
// mainContent.appendChild(addTaskBtn);

完成以上修改后,即可通过弹窗将新任务正确添加到当前激活的项目中。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 19:30:00