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

如何实现点击编辑按钮更新数组对象值并渲染li内容

完善Todo列表的编辑功能

问题描述

需求:点击Edit按钮后,允许用户输入新值,提交后更新对应<li>元素的文本内容,同时更新数组中对应对象的text值。以下是我的JavaScript代码,其中editTask函数尚未完成,其他无关函数可忽略,请教如何完善该功能:

const alertMsg = document.querySelector('.alert-message');
const inputForm = document.querySelector('.input-section');
const todoInput = document.querySelector('.todo-input');
const addBtn = document.querySelector('.add-btn');
const taskActions = document.querySelector('.task-actions');
const todosList = document.querySelector('.todos-list');
const deleteAllBtn = document.querySelector('.delete-all-btn');
const savedTodos = localStorage.getItem('todos');

let todos = [];

function displayTodos(newTodoObj){
    const li = document.createElement('li');
    li.id = newTodoObj.id;
    li.className = 'task-container'

    const task = document.createElement('span');
    const checkBtn = document.createElement('button')
    const editBtn = document.createElement('button')
    const deleteBtn = document.createElement('button')

    task.innerText = newTodoObj.text;
    checkBtn.innerText = 'Check'
    editBtn.innerText = 'Edit';
    deleteBtn.innerText = 'Del';

    checkBtn.addEventListener('click', (event) => {
        const task = event.target.parentElement;
        console.log(task);
        task.classList.toggle('completed');
    })

    editBtn.addEventListener('click', editTask)
    deleteBtn.addEventListener('click', deleteTask)

    li.appendChild(task);
    li.appendChild(checkBtn);
    li.appendChild(editBtn);
    li.appendChild(deleteBtn);

    todosList.appendChild(li);
}


function editTask(event){
    const li = event.target.parentElement.children[0].innerText;
    todoInput.value = li;    
}

function deleteTask(event){
    const li = event.target.parentElement;

    li.remove();
    todos = todos.filter((todo) => todo.id !== parseInt(li.id));
    saveTodos();
}

function handleTodoSubmit(event){
    event.preventDefault();
    const newTodo = todoInput.value;
    todoInput.value = '';
    const newTodoObj = {
        text: newTodo,
        id: Date.now(),
        checked: false
    };
    todos.push(newTodoObj);
    displayTodos(newTodoObj);
    saveTodos();
}

function saveTodos(){
    localStorage.setItem('todos', JSON.stringify(todos));
}

inputForm.addEventListener('submit', handleTodoSubmit);

if(savedTodos !== null){
    const parsedTodos = JSON.parse(savedTodos);
    parsedTodos.forEach(displayTodos);
}

window.addEventListener('beforeunload', saveTodos);

解决方案

以下是完善后的代码,核心是通过标记编辑状态,区分新增/编辑逻辑,同时同步更新DOM、数组和本地存储:

const alertMsg = document.querySelector('.alert-message');
const inputForm = document.querySelector('.input-section');
const todoInput = document.querySelector('.todo-input');
const addBtn = document.querySelector('.add-btn');
const taskActions = document.querySelector('.task-actions');
const todosList = document.querySelector('.todos-list');
const deleteAllBtn = document.querySelector('.delete-all-btn');
const savedTodos = localStorage.getItem('todos');

let todos = [];
// 新增变量:跟踪当前编辑的任务ID
let editingId = null;

function displayTodos(newTodoObj){
    const li = document.createElement('li');
    li.id = newTodoObj.id;
    li.className = 'task-container'

    const task = document.createElement('span');
    const checkBtn = document.createElement('button')
    const editBtn = document.createElement('button')
    const deleteBtn = document.createElement('button')

    task.innerText = newTodoObj.text;
    checkBtn.innerText = 'Check'
    editBtn.innerText = 'Edit';
    deleteBtn.innerText = 'Del';

    checkBtn.addEventListener('click', (event) => {
        const task = event.target.parentElement;
        console.log(task);
        task.classList.toggle('completed');
    })

    editBtn.addEventListener('click', editTask)
    deleteBtn.addEventListener('click', deleteTask)

    li.appendChild(task);
    li.appendChild(checkBtn);
    li.appendChild(editBtn);
    li.appendChild(deleteBtn);

    todosList.appendChild(li);
}


function editTask(event){
    // 获取当前任务的父元素li
    const li = event.target.parentElement;
    // 记录要编辑的任务ID
    editingId = parseInt(li.id);
    // 获取当前任务文本并填充到输入框
    const taskText = li.querySelector('span').innerText;
    todoInput.value = taskText;
    // 自动聚焦输入框提升体验
    todoInput.focus();
}

function deleteTask(event){
    const li = event.target.parentElement;

    li.remove();
    todos = todos.filter((todo) => todo.id !== parseInt(li.id));
    saveTodos();
}

function handleTodoSubmit(event){
    event.preventDefault();
    const newTodoText = todoInput.value.trim();
    if (!newTodoText) return; // 空内容不提交

    if (editingId !== null) {
        // 编辑模式:更新现有任务
        // 1. 更新数组中的任务对象
        todos = todos.map(todo => {
            if (todo.id === editingId) {
                return {...todo, text: newTodoText};
            }
            return todo;
        });
        // 2. 更新DOM中的任务文本
        const targetLi = document.getElementById(editingId);
        targetLi.querySelector('span').innerText = newTodoText;
        // 3. 重置编辑状态
        editingId = null;
    } else {
        // 新增模式:创建新任务
        const newTodoObj = {
            text: newTodoText,
            id: Date.now(),
            checked: false
        };
        todos.push(newTodoObj);
        displayTodos(newTodoObj);
    }
    
    todoInput.value = '';
    saveTodos();
}

function saveTodos(){
    localStorage.setItem('todos', JSON.stringify(todos));
}

inputForm.addEventListener('submit', handleTodoSubmit);

if(savedTodos !== null){
    const parsedTodos = JSON.parse(savedTodos);
    todos = parsedTodos; // 初始化todos数组(原代码遗漏此步骤)
    parsedTodos.forEach(displayTodos);
}

window.addEventListener('beforeunload', saveTodos);

关键修改说明

  • 新增editingId全局变量,标记当前是否处于编辑状态及目标任务ID
  • 完善editTask函数:获取目标任务的ID和文本,填充输入框并记录编辑状态
  • 修改handleTodoSubmit函数:
    • 先判断是否处于编辑状态,若是则更新数组中对应任务的text值,同时修改DOM中对应<span>的文本
    • 编辑完成后重置editingId,恢复新增模式
  • 补充todos数组的初始化(原代码从localStorage读取后未赋值给todos,会导致编辑时数组为空)
  • 增加输入内容的空值判断,避免提交空任务

内容的提问来源于stack exchange,提问作者Anthony Renzo Ferrer

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 07:20:39