JavaScript 实战 —— 实现一个简易的 TodoList(适合前端入门 / 进阶)

一、学习目标

掌握 JavaScript DOM 操作、事件绑定、本地存储(localStorage),实现一个可添加、删除、修改、勾选的 TodoList,适合前端入门或想巩固 DOM 操作的程序员。

二、核心知识点

  • DOM 操作:创建元素、删除元素、修改元素内容与样式
  • 事件绑定:click、input 事件,事件委托(优化性能)
  • localStorage:本地存储数据,实现页面刷新后数据不丢失
  • 数组方法:forEach、filter、map 的实际应用

三、实战代码(可直接运行,复制到 HTML 文件即可)

html

预览

复制代码
<html lang="zh-CN">
<head>
    <meta charset="UTF-8<meta name="viewport" content="width=device-width, initial-scale=1.0">
   简易TodoList
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            font-family: 'Arial', sans-serif;
        }
        .container {
            width: 500px;
            margin: 50px auto;
            padding: 20px;
            border: 1px solid #eee;
            border-radius: 8px;
            box-shadow: 0 0 10px rgba(0,0,0,0.1);
        }
        h1 {
            text-align: center;
            margin-bottom: 20px;
            color: #333;
        }
        .add-todo {
            display: flex;
            gap: 10px;
            margin-bottom: 20px;
        }
        #todo-input {
            flex: 1;
            padding: 10px;
            border: 1px solid #ddd;
            border-radius: 4px;
            font-size: 16px;
        }
        #add-btn {
            padding: 0 20px;
            background: #4CAF50;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            font-size: 16px;
        }
        #add-btn:hover {
            background: #45a049;
        }
        .todo-list {
            list-style: none;
        }
        .todo-item {
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 10px;
            border-bottom: 1px solid #eee;
        }
        .todo-item:hover {
            background: #f9f9f9;
        }
        .todo-content {
            display: flex;
            align-items: center;
            gap: 10px;
        }
        .todo-checkbox:checked + span {
            text-decoration: line-through;
            color: #999;
        }
        .todo-operate {
            display: flex;
            gap: 10px;
        }
        .edit-btn {
            color: #2196F3;
            border: none;
            background: transparent;
            cursor: pointer;
        }
        .delete-btn {
            color: #f44336;
            border: none;
            background: transparent;
            cursor: pointer;
        }
    </head>
<body>
    <div class="container">
<h1>Todo</h1>
<div class="add-todo">
            <input type="text" id="todo-input" placeholder="请输入待办事项...<button id="add-btn">添加</div<ul class="todo-list" id="</ul>
</div>

   <script>
        // 1. 获取DOM元素
        const todoInput = document.getElementById('todo-input');
        const addBtn = document.getElementById('add-btn');
        const todoList = document.getElementById('todo-list');

        // 2. 从本地存储获取todo数据,没有则初始化空数组
        let todos = JSON.parse(localStorage.getItem('todos')) || [];

        // 3. 渲染todo列表
        function renderTodo() {
            // 清空列表,避免重复渲染
            todoList.innerHTML = '';
            // 遍历todos数组,创建每个todo项
            todos.forEach((todo, index) => {
                const li = document.createElement('li');
                li.className = 'todo-item';
                li.innerHTML = `<div class="todo-content">
                        <input type="checkbox" class="todo-checkbox" ${todo.done ? 'checked' : ''}>
                        </span</div><div class="todo-operate">
                       <button class="edit-btn</button>
<button class="delete</button></div>
                `;
                // 将li添加到列表中
                todoList.appendChild(li);

                // 4. 绑定事件(勾选、编辑、删除)
                // 勾选事件
                const checkbox = li.querySelector('.todo-checkbox');
                checkbox.addEventListener('click', () => {
                    todos[index].done = !todos[index].done;
                    // 更新本地存储并重新渲染
                    updateLocalStorage();
                    renderTodo();
                });

                // 编辑事件
                const editBtn = li.querySelector('.edit-btn');
                editBtn.addEventListener('click', () => {
                    const newContent = prompt('请输入修改后的待办事项:', todo.content);
                    if (newContent && newContent.trim() !== '') {
                        todos[index].content = newContent.trim();
                        updateLocalStorage();
                        renderTodo();
                    }
                });

                // 删除事件
                const deleteBtn = li.querySelector('.delete-btn');
                deleteBtn.addEventListener('click', () => {
                    if (confirm('确定要删除这个待办事项吗?')) {
                        todos.splice(index, 1);
                        updateLocalStorage();
                        renderTodo();
                    }
                });
            });
        }

        // 5. 添加todo任务
        function addTodo() {
            const content = todoInput.value.trim();
            if (content === '') {
                alert('请输入待办事项!');
                return;
            }
            // 新增todo对象
            const newTodo = {
                content: content,
                done: false // 初始状态:未勾选
            };
            todos.push(newTodo);
            // 更新本地存储并重新渲染
            updateLocalStorage();
            renderTodo();
            // 清空输入框
            todoInput.value = '';
        }

        // 6. 更新本地存储
        function updateLocalStorage() {
            localStorage.setItem('todos', JSON.stringify(todos));
        }

        // 7. 绑定添加按钮点击事件
        addBtn.addEventListener('click', addTodo);
        // 绑定回车键事件(按下回车也能添加)
        todoInput.addEventListener('keydown', (e) => {
            if (e.key === 'Enter') {
                addTodo();
            }
        });

        // 8. 页面加载时渲染todo列表
        window.addEventListener('load', render</script</body>
</html>

四、代码说明与功能演示

  • 功能说明:可添加待办事项、勾选完成、编辑内容、删除事项,页面刷新后数据不会丢失(通过 localStorage 存储)。
  • 运行方法:将代码复制到记事本,保存为.html 文件(如 todo.html),用浏览器打开即可使用。
  • 核心亮点:使用事件委托的思想(虽然本案例直接绑定,但可优化为事件委托,减少事件绑定数量),localStorage 实现数据持久化,数组方法处理 todo 数据。

五、拓展练习

尝试添加 "清空已完成""按完成状态筛选" 功能,巩固 DOM 操作和数组方法的使用;或优化样式,实现响应式布局,适配手机端。

相关推荐
是上好佳佳佳呀2 小时前
【前端(二)】CSS 知识梳理:从编写位置到选择器优先级
前端·css
向上_503582912 小时前
配置Protobuf输出Java文件或kotlin文件
android·java·开发语言·kotlin
njidf2 小时前
C++中的观察者模式
开发语言·c++·算法
艾莉丝努力练剑2 小时前
alarm系统调用的一次性原理揭秘
linux·运维·服务器·开发语言·网络·人工智能·学习
探序基因2 小时前
安装空间转录组分析软件-R包SPATA2的安装
开发语言·r语言
倾颜2 小时前
我是怎么把单 Tool Calling 升级成多 Tool Runtime 的
前端·后端·langchain
清汤饺子2 小时前
Superpowers:给 AI 编程 Agent 装上"工程化超能力"
前端·javascript·后端
踩着两条虫2 小时前
AI驱动的Vue3应用开发平台 深入探究(十三):物料系统之区块与页面模板
前端·vue.js·人工智能·架构·系统架构
春日见2 小时前
E2E自驾规控30讲:环境搭建
开发语言·驱动开发·matlab·docker·计算机外设