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

无法添加新行:ToDo列表无法生成独立任务卡片求助

解决ToDo列表任务卡片合并问题

你的问题出在复用了同一个任务卡片元素,并且直接把数组内容拼接成文本插入,没有为每个新任务创建独立的DOM元素。要实现每个任务一张独立卡片,需要动态生成新的任务卡片元素,而非复用初始的隐藏卡片。以下是具体修改方案:


1. 调整HTML结构

给每个分类卡片(ToDo/Doing/Done)添加任务容器,用来存放所有动态生成的任务卡片;同时把原有的.adding-task改成模板并隐藏:

<!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>To do list- Projeto de alto escalão</title>
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Open+Sans:wght@300;400;500&display=swap" rel="stylesheet">
    <link rel="stylesheet" href="https://pro.fontawesome.com/releases/v5.10.0/css/all.css" />
</head>
<body>
    <h1>To do list</h1>
    <div class="cards">
        <div class="card redd">
            <p class="stats">🙂 To do</p>
            <!-- 新增:任务容器,用来存放所有动态生成的任务卡片 -->
            <div class="tasks-container"></div>
            <!-- 改为模板,隐藏起来 -->
            <div class="adding-task hide task-template">
                <p class="task-descrip"></p>
                <span class="options">
                    <i class="fas fa-edit" style="margin-right: 2px;"></i>
                    <i class="fas fa-trash-alt"></i>
                </span>
            </div>
            <!-- 添加data-target标记对应的数据数组 -->
            <button class="add-card" data-target="toDo">
                + ADICIONAR TAREFAS
            </button>
        </div>
        <div class="card bluee">
            <p class="stats">😀 Doing</p>
            <div class="tasks-container"></div>
            <div class="adding-task hide task-template">
                <p class="task-descrip"></p>
                <span class="options">
                    <i class="fas fa-edit" style="margin-right: 2px;"></i>
                    <i class="fas fa-trash-alt"></i>
                </span>
            </div>
            <button class="add-card" data-target="doing">
                + ADICIONAR TAREFAS
            </button>
        </div>
        <div class="card pinkk">
            <p class="stats">😎 Done</p>
            <div class="tasks-container"></div>
            <div class="adding-task hide task-template">
                <p class="task-descrip"></p>
                <span class="options">
                    <i class="fas fa-edit" style="margin-right: 2px;"></i>
                    <i class="fas fa-trash-alt"></i>
                </span>
            </div>
            <button class="add-card" data-target="done">
                + ADICIONAR TAREFAS
            </button>
        </div>
    </div>
    <div class="overlay" id="overlay">
        <div class="modal">
            <div class="modal-title">
                <p>Texto da nota</p>
            </div>
            <div class="input-text">
                <input type="text" id="inputText">
            </div>
            <button class="modal-button cancel" id="cancelButton">CANCELAR</button>
            <button class="modal-button" id="confirmButton">CONFIRMAR</button>
        </div>
    </div>
</body>
</html>

2. 修改CSS样式

给任务容器添加间距,让任务卡片排版更美观:

*{
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

:root{
    font-family: Arial, Helvetica, sans-serif;
    --red: rgb(247, 14, 14);
    --pink: rgb(218, 13, 133);
    --blue: rgb(55, 136, 243);
}

body{
    background-color: #f1f1f1;
    padding: 2rem 2rem;
}

.cards{
    display: flex;
    gap: 18px;
    padding-top: 1rem;
    height: fit-content;
    flex-wrap: wrap;
}

.card{
    border-radius: 4px;
    width: 334px;
    padding: 1rem;
    max-width:100%;
    max-height: 100%;
    box-shadow: 3px 4px 10px rgba(0, 0, 0, 0.24);
}
.card.redd{
    background-color: var(--red);
}
.card.bluee{
    background-color: var(--blue);
}
.card.pinkk{
    background-color: var(--pink);
}

.stats{
    color: white;
    font-size: 22px;
    font-weight: 600;
    margin-right: 22px;  
    margin-bottom: 15px; 
}
.add-card{
    border: none;
    background: none;
    color: white;
    font-weight: bold;
    font-size: 15px;
    cursor: pointer;
    margin-left: 4px;
    margin-top: 32px;
}

.overlay{
    background-color: rgba(0, 0, 0, 0.5);
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    display: flex;
    justify-content: center;
    align-items: center;
    display: none;
}

.overlay.in {
    display: flex;
    position: fixed;
}

.modal{
    background-color: white;
    width: 700px;
    height: 170px;
    padding: 2rem 2rem;
    position: relative;
}

.modal-title{
    font-weight: bold;
    font-size: 20px;
    margin-bottom: 30px;
}
#inputText{
    background: none;
    border: none;
    border-bottom: 2px solid rgb(29, 96, 241);
    width: 100%;
    outline: none;
    font-size: 17px;
}    
.modal-button{
    border: none;
    background: none;
    color: rgb(25, 93, 240);
    font-weight: bold;
    font-size: 15px;
    cursor: pointer;
    position: absolute;
    right: 18px;
    bottom: 20px;
}
.modal-button.cancel{
    margin-right: 107px;
}
.adding-task{
    width:100%;
    height: fit-content;
    background-color: white;
    padding: 21px 15px;
    border-radius: 6px;
    display: flex;
    justify-content: space-between;
    gap: 18px;
}
.adding-task.hide{
    display: none;
}

.task-descrip{
    font-weight: bold;
    font-size: 15px;
    font-family: 'Open Sans', sans-serif;
    word-wrap: break-word;
    word-break: break-all;
}
.options{
    cursor: pointer;
}

/* 新增:任务容器样式 */
.tasks-container {
    display: flex;
    flex-direction: column;
    gap: 12px;
    margin-bottom: 20px;
}

3. 重写JavaScript逻辑

核心修改:动态克隆任务模板生成新卡片,记录当前要添加任务的目标分类,同步更新数据和DOM:

//CRUD (Create, Read, Update, Delete) -> allows you to create data, read data, edit it, and delete those data.

// Passo 1: mostrar o MODAL (CREATE)
const overlay = document.querySelector('.overlay'); 
let currentTargetContainer = null; // 当前要添加任务的容器
let currentDataKey = null; // 当前要添加到的数据数组键名

function showModal() {
    overlay.classList.add("in");
}

// Passo 2: Esconder o MODAL
function hideModal() {
    overlay.classList.remove("in");
    input.value = ""; // 清空输入框
}

//Passo 3: CHAMAR AS FUNÇÕES Quando clicamos no botão
const buttons = document.querySelectorAll(".add-card");

buttons.forEach((btn) => {
    btn.onclick = (event) => {
        showModal();
        // 获取当前按钮对应的卡片容器和数据键名
        currentDataKey = btn.dataset.target;
        currentTargetContainer = btn.parentElement.querySelector('.tasks-container');
    }
})

const modalCancel = document.querySelector('.modal-button.cancel');
modalCancel.addEventListener('click', hideModal);

//Passo 4 - Fazer o botão CONFIRMAR funcionar & pegar o valor do input;
const modalConfirm = document.querySelector('#confirmButton');
let input = document.getElementById('inputText');
const taskTemplate = document.querySelector('.task-template'); // 获取任务模板

const data = {
    toDo: [],
    doing: [],
    done: []
};

// 创建新任务卡片的函数
function createTaskCard(taskText) {
    // 克隆模板节点,true表示克隆所有子元素
    const newTaskCard = taskTemplate.cloneNode(true);
    newTaskCard.classList.remove('hide', 'task-template'); // 移除隐藏和模板类
    // 设置任务文本
    newTaskCard.querySelector('.task-descrip').textContent = taskText;
    // 添加删除按钮事件
    newTaskCard.querySelector('.fa-trash-alt').addEventListener('click', () => {
        // 从数据数组中移除该任务
        data[currentDataKey] = data[currentDataKey].filter(item => item !== taskText);
        // 移除DOM元素
        newTaskCard.remove();
    });
    return newTaskCard;
}

//Passo 5 - Adicionar alguma tarefa no container;
function confirmButton() {
    modalConfirm.addEventListener('click', () => {
        hideModal();
        const inputValue = input.value.trim();
        if (!inputValue) return; // 空输入不处理

        // 更新数据数组
        data[currentDataKey].push(inputValue);
        // 创建新任务卡片并添加到目标容器
        const newCard = createTaskCard(inputValue);
        currentTargetContainer.appendChild(newCard);
    });
}

confirmButton();

关键修改点说明

  1. 动态生成卡片:不再复用单个任务卡片,而是通过克隆模板创建新的独立DOM元素,每个任务对应一张卡片
  2. 分类关联:用data-target属性关联添加按钮和对应的数据数组,支持三个分类的任务添加
  3. 数据同步:添加/删除任务时同步更新数据数组和DOM元素
  4. 空输入校验:避免添加空任务

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 10:57:01