Как избежать дублирования элементов при использовании appendChild в цикле JavaScript?

Проблема с дублированием задач в списке

Изучаю JavaScript и столкнулся с проблемой при создании динамического списка дел. Когда пользователь добавляет новую задачу, функция отображения создает копии всех предыдущих элементов в DOM.

Мой код:

const todoItems = JSON.parse(localStorage.getItem('todoItems')) || [];
const addButton = document.querySelector('.add-btn');

displayTodos();

function displayTodos() {
    const container = document.querySelector('.todo-container');
    const docFragment = document.createDocumentFragment();
    
    for (const [index, item] of todoItems.entries()) {
        const { title, deadline } = item;
        const titleDiv = document.createElement('div');
        const deadlineDiv = document.createElement('div');
        const deleteBtn = document.createElement('button');
        
        titleDiv.className = 'todo-title';
        deadlineDiv.className = 'todo-deadline';
        deleteBtn.className = 'btn delete-btn';
        deleteBtn.textContent = 'Удалить';
        
        deleteBtn.addEventListener('click', () => {
            removeTodo(index);
        });
        
        titleDiv.textContent = title;
        deadlineDiv.textContent = deadline;
        
        docFragment.appendChild(titleDiv);
        docFragment.appendChild(deadlineDiv);
        docFragment.appendChild(deleteBtn);
    }
    container.appendChild(docFragment);
}

function removeTodo(idx) {
    todoItems.splice(idx, 1);
    displayTodos();
    saveToStorage();
}

Как правильно сравнивать DOM элементы и предотвратить создание дубликатов при каждом вызове функции отображения?

Твоя displayTodos() каждый раз перерисовывает всё, а старые элементы висят в контейнере. Сделай функцию addTodoElement() для одного элемента вместо полной перерисовки. Для удаления используй remove() на конкретном DOM-элементе. С большими списками будет работать намного быстрее.

The Problem:

Вы столкнулись с проблемой дублирования задач в динамическом списке дел при добавлении новых элементов. Функция displayTodos() создает копии всех предыдущих элементов в DOM при каждом вызове.

:thinking: Understanding the “Why” (The Root Cause):

Проблема заключается в том, что функция displayTodos() каждый раз добавляет новые элементы в контейнер, не удаляя старые. В результате, при каждом добавлении задачи, все существующие задачи отображаются повторно, создавая дубликаты. Ваш код создает фрагмент документа (documentFragment), но не очищает контейнер (todo-container) перед добавлением нового фрагмента.

:gear: Step-by-Step Guide:

  1. Очистите контейнер перед добавлением новых элементов: Добавьте строку кода container.innerHTML = ''; в начале функции displayTodos(). Это очистит содержимое контейнера перед добавлением новых элементов, предотвращая дублирование.
function displayTodos() {
    const container = document.querySelector('.todo-container');
    container.innerHTML = ''; // Очищаем контейнер
    const docFragment = document.createDocumentFragment();

    // ... остальной код функции displayTodos() ...
}
  1. (Optional) Более эффективное решение: Для больших списков задач, перерисовка всего списка может быть неэффективной. Рассмотрите возможность создания функции addTodoElement(), которая добавляет только один элемент в список, вместо перерисовки всего списка. Удаление элементов можно производить с помощью метода remove() на конкретном DOM-элементе, а не путем перерисовки всего списка. Это значительно улучшит производительность.

:mag: Common Pitfalls & What to Check Next:

  • Проверьте селектор: Убедитесь, что document.querySelector('.todo-container') действительно выбирает правильный элемент. Используйте инструменты разработчика браузера для проверки.
  • Проверьте порядок выполнения: Убедитесь, что displayTodos() вызывается в нужном месте и после всех операций с массивом todoItems.
  • Альтернативные решения: Изучите использование виртуального DOM (например, с помощью библиотеки React или Vue) для более эффективного управления изменениями в DOM, особенно при работе с большими объемами данных.

:speech_balloon: Still running into issues? Share your (sanitized) config files, the exact command you ran, and any other relevant details. The community is here to help!