ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

构建模块化 Todo List 应用:Odin 课程 JavaScript 综合实战(工厂函数、ES6 模块与 localStorage 持久化)

构建模块化 Todo List 应用:Odin 课程 JavaScript 综合实战(工厂函数、ES6 模块与 localStorage 持久化) 构建模块化 Todo List 应用Odin 课程 JavaScript 综合实战工厂函数、ES6 模块与 localStorage 持久化【免费下载链接】curriculumThe open curriculum for learning web development项目地址: https://gitcode.com/GitHub_Trending/cu/curriculum本指南基于 curriculum 仓库中的javascript/organizing_your_javascript_code/project_todo_list.md项目作业系统讲解如何用当前课程已学的全部前端技术从零构建一个功能完整的 Todo List 应用。你将掌握用工厂函数或类动态生成 todo 对象、用项目Projects组织任务、将应用逻辑与 DOM 操作拆分为独立模块、通过 npm 引入 date-fns 处理日期以及借助 Web Storage APIlocalStorage实现数据持久化最终产出一个可刷新不丢数据、可扩展的真实 Web 应用。项目定位把前序技术拧成一股绳的收官之作在 JavaScript 组织代码这一阶段你已经先后接触了对象构造函数、工厂函数与模块模式IIFE、ES6 模块import/export、npm 包管理、Webpack 打包以及 JSON 数据格式。Todo List 项目的意义在于它不是引入新知识而是要求你把上述技术全部应用到同一个真实项目中通过实践检验对闭包、模块化、依赖管理、数据序列化这些概念的掌握程度。与上一个 Library 项目图书管理相比Todo List 在架构上更进一步Library 主要练习用一个数组 构造函数管理一组对象而 Todo List 要求你引入多级数据组织项目 → 任务、应用逻辑与 DOM 彻底分离以及浏览器本地持久化复杂度上了一个台阶。因此在动手写代码之前务必先花几分钟规划项目结构目录怎么分、模块怎么拆、数据流怎么走。规划得越清晰后面写代码越顺利。动态创建 todo 对象工厂函数、构造函数与类的选型Todo List 的第一个硬性要求是todos 是动态创建的对象必须使用工厂函数、构造函数或 class 来生成而不是手工写一个个对象字面量。用工厂函数实现推荐起点在 factory_functions_and_module_pattern.md 中已经详细讲过工厂函数就是返回对象的普通函数它借力闭包实现私有变量无需new关键字调用。一个 todo 工厂可以这样设计function createTodo(title, description, dueDate, priority) { let completed false; const getCompleted () completed; const toggleCompleted () { completed !completed; }; return { title, description, dueDate, priority, getCompleted, toggleCompleted }; }这里completed状态被刻意做成私有变量外部无法直接todo.completed true绕过逻辑只能通过toggleCompleted()改变它——这正是 private variables 与闭包 一节的实战应用。工厂函数还天然支持组合如果你想给 todo 增加清单checklist能力可以通过Object.assign组合多个来源的对象这比继承更灵活。用 class 实现如果你更习惯 classes.md 中介绍的 ES6 class 语法也可以这样写class Todo { #completed false; // 私有字段 constructor(title, description, dueDate, priority) { this.title title; this.description description; this.dueDate dueDate; this.priority priority; } get completed() { return this.#completed; } toggleCompleted() { this.#completed !this.#completed; } }class 语法在底层仍是基于原型链但它提供了更显式的constructor、getter/setter与#私有字段语法适合偏好面向对象风格的开发者。两种方案都能满足动态创建 todo 对象的要求选哪种取决于你更熟悉哪种模式——保持一致即可不必在同一个项目里混用。设计 todo 的属性从最小集到增强集作业要求 brainstorm头脑风暴todo 对象的属性并给出一个最低标准属性说明title任务标题必填description任务详细描述必填dueDate截止日期必填priority优先级必填notes备注可选扩展checklist子任务清单可选扩展completed完成状态用于设为完成功能逻辑上必需最低标准之外可以自由发挥。比如priority建议用固定枚举值如low/medium/high而不是自由文本这样便于后续用颜色区分checklist可以是子任务对象数组同样用工厂或类生成。设计属性时始终记住这些属性最终会通过 JSON 序列化写入 localStorage因此只放可序列化的数据字符串、数字、布尔、数组、普通对象函数与方法不直接存储详见下文持久化章节。用 Projects 组织任务默认项目 多项目切换Todo List 的核心数据结构是两级嵌套Projects项目→ Todos任务。作业明确要求应用首次打开时必须存在一个默认项目所有新建 todo 默认放入其中用户可以创建新项目并在创建 todo 时选择它要归属的项目。典型的数据结构如下// 项目对象包含一个 todo 数组 function createProject(name, todos []) { return { name, todos }; } // 应用状态一个项目数组索引 0 作为默认项目 let projects [createProject(默认项目)]; // 新建 todo 并放入指定项目 function addTodoToProject(project, todo) { project.todos.push(todo); saveToLocalStorage(); // 每次变更后立即持久化 }在设计阶段就应想清楚几个问题如何定位一个项目用索引、名称还是唯一 id删除 todo 时如何从对应数组移除切换项目视图时如何重新渲染借鉴 project_library.md 的经验为每个 todo 生成一个唯一id可用crypto.randomUUID()并在 DOM 元素上用data-*属性与之关联是处理增删改时保持数据与界面同步的稳妥方案。模块化把应用逻辑与 DOM 操作彻底分开这是整个项目最重要的一条架构纪律应用逻辑创建 todo、标记完成、修改优先级、项目增删、数据持久化与 DOM 相关代码渲染列表、绑定事件、打开编辑弹窗必须放在不同的模块里。课程在 es6_modules.md 中讲解了 ES6 模块的export/import语法与入口点概念在 webpack.md 中讲解了如何用 Webpack 把这些模块打包进dist。一个推荐的目录划分src/ ├── index.js # 入口点初始化应用、首次渲染 ├── todo.js # todo 工厂/类生成 todo 对象 ├── project.js # project 工厂/类生成项目对象 ├── storage.js # localStorage 读写序列化与反序列化 ├── dom/ │ ├── render.js # 渲染项目列表与 todo 列表 │ └── events.js # 表单提交、按钮点击等事件绑定 └── template.html # HtmlWebpackPlugin 使用的模板模块之间的依赖关系是单向的dom/模块只负责读状态 渲染 转发用户操作它调用todo.js/project.js的工厂生成新对象调用storage.js做持久化而todo.js/storage.js完全不碰 DOM。这样带来的直接好处是未来改用别的渲染方式比如框架时核心数据逻辑一行都不用改——这正是 project_library.md 中把显示逻辑与数据结构视为不同实体理念的延续与强化。模块之间通过命名导出互通例如// storage.js export function saveProjects(projects) { /* ... */ } export function loadProjects() { /* ... */ } // index.js入口点 import { loadProjects } from ./storage.js; import { renderProjects } from ./dom/render.js;UI 功能清单四条必做交互界面外观可以自由设计但必须满足以下四个功能点查看所有项目侧边栏或顶栏列出全部 project当前选中的项目有明确高亮查看每个项目内的所有 todo通常只显示标题与截止日期不同priority用不同颜色标识例如 high 红色、medium 橙色、low 绿色展开单个 todo 查看/编辑详情点击可展开显示description、notes、checklist等完整字段并支持编辑保存删除 todo每个 todo 上有删除按钮点击后从对应项目的todos数组中移除并重新渲染。可以参考 Todoist、Things、any.do 这三款经典待办应用的界面截图与介绍视频寻找灵感——重点观察它们如何处理项目侧栏 任务主区 详情面板的布局以及编辑、删除、完成状态切换的交互方式。用 npm 引入 date-fns 处理日期由于项目已经基于 Webpack 工作见 webpack.md 与 npm.md引入第三方库非常方便。作业建议使用date-fns来格式化与操作日期npm install date-fns它按需导出、tree-shaking 友好例如在渲染截止日期时import { format, isAfter } from date-fns; // 将存储的日期字符串格式化为人类可读形式 const prettyDueDate format(new Date(todo.dueDate), yyyy-MM-dd); // 判断任务是否已过期 const overdue isAfter(new Date(), new Date(todo.dueDate));注意date-fns 这类库的代码会随 Webpack 一起被打包进dist/main.js因此应作为普通依赖dependencies安装而不是开发依赖--save-dev。如果不用 date-fns也可以手写原生Date方法但日期格式化与比较的边界情况很多成熟库能省去大量踩坑时间。用 localStorage 实现数据持久化到目前为止你还没有学过任何服务端存储技术因此刷新页面后 todos 会全部消失。作业要求用Web Storage API 的 localStorage把数据保存在用户浏览器本地实现持久化。基本读写流程localStorage 只能存字符串而我们的数据结构是嵌套对象所以必须借助 JSON 序列化。这一点在 json.md 中已有铺垫JSON.stringify()把对象转为字符串JSON.parse()把字符串还原为对象。// storage.js const STORAGE_KEY todoApp.projects; // 每次创建新项目或新 todo 后调用保存 export function saveProjects(projects) { localStorage.setItem(STORAGE_KEY, JSON.stringify(projects)); } // 应用首次加载时调用读取 export function loadProjects() { const raw localStorage.getItem(STORAGE_KEY); return raw ? JSON.parse(raw) : []; }三个必须注意的坑坑一读取时数据可能不存在。用户第一次打开应用时 localStorage 里什么都没有getItem返回null。必须先判空再解析否则JSON.parse(null)会直接抛错导致整个应用崩溃const raw localStorage.getItem(STORAGE_KEY); const projects raw ? JSON.parse(raw) : [createProject(默认项目)];坑二JSON 存不了函数方法不会自动回来。这是最隐蔽的问题JSON.stringify会静默丢弃对象上的方法因此从 localStorage 读回来的 todo 对象只有数据属性没有任何方法比如工厂函数返回的toggleCompleted会消失。你必须自己设计还原逻辑——例如读回纯数据后用工厂函数或类重新包装一遍把方法挂回去function hydrateTodo(rawTodo) { const todo createTodo(rawTodo.title, rawTodo.description, rawTodo.dueDate, rawTodo.priority); if (rawTodo.completed) todo.toggleCompleted(); return todo; }坑三只把要存的字段存进去。反过来写的时候也一样确认存入的是可序列化的纯数据字符串、数字、布尔、数组、普通对象不要尝试把闭包里的私有变量或方法存进 JSON——它们本来就无法被序列化。用 DevTools 检查 localStorage浏览器开发者工具DevTools可以实时查看 localStorage 内容打开Application面板在Storage分组下点击Local Storage选项卡。应用中每执行一次setItem新增、更新、删除数据这里都会即时刷新。这是调试持久化逻辑最直接的手段可以确认数据是否写入、JSON 结构是否符合预期、删除操作是否真正生效。建议的开发顺序与自查清单为避免在项目中途陷入逻辑改不动、界面一锅粥的困境建议按以下顺序推进先写todo.js/project.js的工厂或类用控制台手动创建对象、验证方法写storage.js的存取函数验证序列化/反序列化往返一致尤其验证方法是否丢失写入口点index.js初始化默认项目从 localStorage 恢复数据不存在则创建默认项目写dom/render.js实现查看所有项目与查看项目内所有 todo两个基础视图补上新建 todo 表单记得event.preventDefault()阻止表单默认提交行为、展开详情编辑与删除 todo三个交互引入 date-fns 优化日期显示与过期判断全程用 Webpack 打包并在npx webpack serve开发服务器下验证刷新页面确认数据不丢失。完成后再对照以下问题自查todo 是否由工厂/类动态生成属性是否覆盖 title、description、dueDate、priority及你扩展的字段是否有默认项目且能创建/切换新项目应用逻辑与 DOM 是否在不同模块四个 UI 功能是否齐全刷新后数据是否还在如果全部通过恭喜——你已经完成了一个架构清晰、可持久化、可扩展的完整前端应用这正是本课程 JavaScript 组织代码阶段所有知识的综合演练场。【免费下载链接】curriculumThe open curriculum for learning web development项目地址: https://gitcode.com/GitHub_Trending/cu/curriculum创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表