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

React.js中点击Done按钮如何为指定列表项添加删除线样式?

React Todo列表Done按钮无效果的解决方法

你的问题核心在于错误地试图直接修改字符串的style属性,而且违背了React状态驱动渲染的原则——React的UI是由状态决定的,不能直接操作DOM元素来改变样式,必须通过更新状态来触发重新渲染。

问题分析

当前tasks数组存储的是纯字符串,tasks[index]是字符串类型,根本没有style属性,所以tasks[index].style.textDecoration = "line-through"这段代码完全无效。同时,就算你能拿到DOM元素,直接操作DOM也不是React的正确做法,状态变化才应该是UI更新的唯一触发源。

解决方案步骤

  1. 修改任务数据结构:把tasks数组的元素从字符串改成对象,每个对象包含任务文本和完成状态(比如{ text: '任务内容', isDone: false })。
  2. 更新添加任务逻辑:添加新任务时,存入包含文本和完成状态的对象。
  3. 重写Done按钮的点击逻辑:通过更新状态来切换对应任务的完成状态。
  4. 根据状态渲染样式:在渲染任务时,根据完成状态动态添加删除线样式。

修改后的完整代码

function Todo(){
    // 修改tasks的初始状态为存储对象的数组
    const [tasks, setTasks] = useState([]);
    const [newTask, setNewTask] = useState("");

    function handleChange(event){
        setNewTask(event.target.value);
    }

    function updateTodo(){
        if(newTask.trim() !== ""){        
            // 添加新任务时存入包含text和isDone的对象
            setTasks(prevTasks => [...prevTasks, { text: newTask, isDone: false }]);
            setNewTask("");
        }
    }

    function deleteTask(index){
        const updatedTasks = tasks.filter((_, i) => i !== index);
        setTasks(updatedTasks);
    }

    function toggleDone(index){
        // 遍历tasks,翻转对应索引任务的isDone状态
        const updatedTasks = tasks.map((task, i) => {
            if(i === index){
                return { ...task, isDone: !task.isDone };
            }
            return task;
        });
        setTasks(updatedTasks);
    }

    return(
        <div id="main">
            <h1>To-Do List</h1>
            <div id="add">
                <input 
                    type="text" 
                    id="add_item" 
                    placeholder='Enter your task' 
                    value={newTask} 
                    onChange={handleChange}
                />
                <input 
                    type="button" 
                    id="add_button" 
                    onClick={updateTodo} 
                    value="Submit"
                />
            </div>
            <div id="list">
                <ol>
                    {tasks.map((task, index) => (
                        <li key={index}>
                            {/* 根据isDone状态动态设置样式 */}
                            <div 
                                className="list_item"
                                style={{ textDecoration: task.isDone ? "line-through" : "none" }}
                            >
                                {task.text}
                            </div>
                            <div className="button_container">
                                <button className="delete" onClick={() => deleteTask(index)}>Delete</button>
                                <button className="done" onClick={() => toggleDone(index)}>Done</button>
                            </div>
                        </li>
                    ))}
                </ol>
            </div>
        </div>
    )
}

关键修改点说明

  • 数据结构变更:用{ text: '', isDone: false }对象存储任务,让每个任务自带完成状态标记。
  • toggleDone函数:通过map方法创建新数组,避免直接修改原状态数组(React状态是不可变的),翻转对应任务的isDone值后更新状态。
  • 动态样式渲染:在list_item的div上,通过内联样式style={{ textDecoration: task.isDone ? "line-through" : "none" }}根据完成状态决定是否显示删除线。

额外优化建议

  • 不要用索引作为key:如果任务有删除操作,索引会发生变化,可能导致渲染异常。可以给每个任务生成唯一ID(比如用Date.now()或者第三方库如uuid),把ID作为key值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 04:26:04