JavaScript待办清单代码模块化拆分及整合指导请求
JavaScript待办清单代码模块化拆分及整合指导请求
我完全懂你现在的困扰——看着这段能跑的Todo代码,想拆成模块却摸不着门道,之前自己试还把控制流搞乱了,肯定特别闹心。咱们一步步来,把这段代码拆成职责清晰的小模块,同时保证功能丝毫不差,还能让代码更易维护。
先理清原代码的核心职责
你的代码主要负责这几件事:
- 初始化绑定添加按钮的事件(
select()) - 处理添加新任务的完整逻辑(
addItem()) - 处理删除任务的逻辑(
deleteItem()) - 输入框回车提交任务内容的交互
- 全局样式重置和Todo专属样式
我们按照单一职责原则把JS拆成3个模块+1个入口文件,每个模块只干一件事:
第一步:拆分模块
1. 通用DOM工具模块:dom-utils.js
这个模块专门处理重复的DOM操作,把通用的选择、创建元素逻辑抽出来,避免在业务代码里重复写document.querySelector:
// dom-utils.js // 获取主任务容器 export const getMainContainer = () => document.querySelector('.main'); // 创建带类名的元素(减少重复代码) export const createElementWithClass = (tag, className) => { const element = document.createElement(tag); element.classList.add(className); return element; }; // 获取添加任务按钮 export const getAddButton = () => document.querySelector('.add-btn');
2. Todo核心操作模块:todo-actions.js
这里放添加、删除任务的核心业务逻辑,依赖上面的DOM工具模块:
// todo-actions.js import { getMainContainer, createElementWithClass } from './dom-utils.js'; // 绑定删除任务的事件 export const setupDeleteHandler = (deleteButton, taskItem) => { deleteButton.addEventListener('click', () => { const main = getMainContainer(); main.removeChild(taskItem); }); }; // 处理输入框回车提交逻辑 const setupInputEnterHandler = (inputArea, taskItem) => { inputArea.addEventListener('keydown', ({ key }) => { if (key === 'Enter' && inputArea.value.trim() !== '') { const textValue = inputArea.value; const displayText = createElementWithClass('p', 'txt-val'); displayText.innerText = textValue; taskItem.appendChild(displayText); taskItem.removeChild(inputArea); } }); }; // 添加新任务的完整流程 export const addNewTask = () => { const main = getMainContainer(); const taskCount = main.children.length; // 创建任务相关元素 const taskItem = createElementWithClass('div', 'new-div'); const taskHeading = createElementWithClass('h2', 'new-heading'); const deleteButton = createElementWithClass('button', 'delete-btn'); const inputArea = createElementWithClass('input', 'textbox'); // 设置元素属性 taskHeading.innerText = `Task ${taskCount}`; deleteButton.innerText = 'Delete'; inputArea.type = 'text'; inputArea.placeholder = 'Enter here...'; // 组装任务元素并添加到页面 taskItem.append(taskHeading, deleteButton, inputArea); main.appendChild(taskItem); // 绑定交互事件 setupInputEnterHandler(inputArea, taskItem); setupDeleteHandler(deleteButton, taskItem); inputArea.focus(); // 自动聚焦输入框 };
3. 应用入口模块:app.js
这是整个应用的启动文件,负责初始化所有交互:
// app.js import { getAddButton } from './dom-utils.js'; import { addNewTask } from './todo-actions.js'; // 初始化Todo应用 const initTodoApp = () => { const addButton = getAddButton(); addButton.addEventListener('click', addNewTask); }; // 启动应用 initTodoApp();
第二步:调整HTML文件
你的HTML只需要把原来的JS引用改成模块形式,注意要加type="module":
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Todo List New</title> <link rel="stylesheet" href="/CSS/Todo List New.css"> </head> <body> <h1>Todo List</h1> <div class="main"> <div class="main-button-class"> <button type="button" class="add-btn">Add Task</button> </div> </div> <!-- 用模块方式引入入口文件 --> <script type="module" src="/JavaScript/app.js"></script> </body> </html>
关键注意事项
- 文件路径要对应:确保
dom-utils.js、todo-actions.js、app.js都放在/JavaScript/目录下,和你原来的JS文件位置一致。 - 模块作用域:模块里的变量/函数默认都是内部私有的,不会污染全局环境,这也是模块化的核心优势之一。
- 本地测试避免跨域:如果直接用浏览器打开本地HTML文件,可能会遇到CORS错误,建议用VS Code的Live Server插件启动本地服务器,模块就能正常加载了。
- 依赖自动处理:浏览器会根据
import语句自动加载依赖模块,不用你手动管加载顺序。
原CSS代码保持不变
你的CSS写得很规范,直接保留在/CSS/Todo List New.css里即可:
*, ::before, ::after { box-sizing: border-box; margin: 0; padding: 0; } h1 { text-align: center; margin-top: 2em; text-decoration: underline; font-size: 3em; } .main { margin-top: 3em; border-right: 12px solid rgb(108, 179, 202); border-left: 12px solid rgb(108, 179, 202); border-top: 8px solid rgb(108, 179, 202); border-bottom: 8px solid rgb(108, 179, 202); height: 100%; position: relative; } .add-btn { background-color: rgb(74, 184, 74); color: white; font-weight: bolder; font-size: x-large; padding: 10px; border: none; border-radius: 10px; cursor: pointer; height: 2em; position: absolute; translate: -2.5em -1.1em; z-index: 1000; } .add-btn:hover { background-color: rgb(112, 219, 112); transition: 0.5s; } .main-button-class { text-align: center; } .new-heading { font-family: Georgia, 'Times New Roman', Times, serif; } .new-div { position: relative; border: 5px solid rgb(84, 153, 218); margin-top: 65px; margin-bottom: 30px; margin-left: 32px; margin-right: 32px; padding: 15px; height: 170px; text-align: center; } .delete-btn { width: 65px; height: 50px; background-color: red; color: white; font-weight: bold; font-size: large; border-radius: 10px; position: absolute; top: 0; right: 0; translate: 25px -25px; cursor: pointer; border: none; } .textbox { width: 95%; height: 80px; margin-top: 15px; padding: 15px; border: 1px solid black; } .txt-val { font-size: x-large; color: black; margin-top: 35px; } .delete-btn:hover { background-color: rgb(255, 105, 105); transition: 0.5s; }
这样拆分之后,每个模块职责明确,代码结构清晰,完全保留了你原来的所有功能,再也不会出现控制流混乱的问题啦!
内容来源于stack exchange
相关产品推荐
相关产品推荐

