- 文档
- 教程
【免费下载链接】app-ideas
A Collection of application ideas which can be used to improve your coding skills.
导读
本文以 App Ideas 仓库 中 Notes App(Tier 1-Beginner)为蓝本,系统讲解如何在纯前端环境中实现一个支持创建、编辑、删除,并在关闭浏览器后依然保留数据的在线记事本。读完后你将掌握 localStorage 的读写与序列化技巧、笔记数据模型的建模方法,以及基于 marked 的 Markdown 渲染流程,可直接落地为一个完整可运行的小项目。
一、项目定位:为什么要做 Notes App
Notes App 是 App Ideas 仓库中面向入门开发者(Tier 1-Beginner)的练习项目之一,其核心目标只有一句话:Create and store your notes for later purpose!(创建笔记并将其存储起来,供日后使用)。
在 README.md 的 Tier 1 开发者画像中,这一级别面向的是"处于学习早期阶段、专注于构建面向用户应用"的开发者。Notes App 恰好覆盖了这类学习者最需要锻炼的三项基础能力:
- 表单输入与页面元素的读取、更新;
- 数据在浏览器端的持久化存储;
- 简单的列表增删改逻辑(CRUD 中的 Create / Update / Delete)。
它不依赖任何后端服务、不需要数据库配置、甚至不需要构建工具,纯 HTML/CSS/JavaScript 即可完成,因此非常适合作为前端入门后的第一个"能留存数据"的完整应用。
二、需求拆解:必须实现的四条 User Story
原文档明确列出了四条必须实现的核心用户故事:
- 用户可创建一条笔记(User can create a note)
- 用户可编辑一条笔记(User can edit a note)
- 用户可删除一条笔记(User can delete a note)
- 关闭浏览器窗口后笔记仍被保存,用户再次回来时数据可被恢复(When closing the browser window the notes will be stored and when the User returns, the data will be retrieved)
前三条构成了最基础的增删改逻辑,第四条则是整个项目的灵魂——数据持久化。它要求应用把笔记数据写入浏览器本地存储,而不是放在内存变量里,否则刷新页面数据就会丢失。
按照仓库中 Example Guide.md 所描述的规范,每份项目文档的 User Stories 是"作为指南而非强制 To-Do 列表",开发者完全可以在四条基础故事之上自行扩展。但四条必须全部完成,才算达到文档定义的最低完成标准。
三、核心技术选型:localStorage 持久化方案
原文档在 "Useful links and resources" 中指向了localStorage(MDN 的 Window.localStorage API),这正是浏览器端实现跨会话持久化最简单、最直接的方式。
3.1 localStorage 的基本特性
- localStorage 以键值对(key-value)形式存储数据,键和值都是字符串;
- 数据跨会话保留,关闭标签页或浏览器窗口后依然存在,直到被代码显式清除或用户手动清理浏览器数据;
- 数据保存在**特定源(origin)**下,不同协议/域名/端口的页面之间互不可见;
- 存储容量通常有限(一般约为 5MB 量级,不同浏览器略有差异),不适合存放大量图片、视频等大体积数据。
由于值必须是字符串,结构化数据(如笔记对象数组)需要先JSON.stringify()序列化再写入,读取时再用JSON.parse()还原。
3.2 数据模型设计
Notes App 的每条笔记至少需要三个字段:
| 字段 | 类型 | 说明 |
|---|---|---|
id | 字符串/数字 | 唯一标识,用于定位要编辑或删除的笔记 |
title | 字符串 | 笔记标题 |
content | 字符串 | 笔记正文(纯文本或 Markdown 源码) |
createdAt | 字符串 | 创建时间(进阶功能需要展示日期) |
存储键建议使用单一命名空间,例如notes,整个应用只用这一个键保存一个笔记数组:
// 读取 const raw = localStorage.getItem('notes'); const notes = raw ? JSON.parse(raw) : []; // 写入(在每次增删改之后调用) function saveNotes(notes) { localStorage.setItem('notes', JSON.stringify(notes)); }这样的"一次读取、整体回写"模式在笔记数量不多时足够简洁可靠,是初学者最容易理解与调试的方案。
补充说明:如果应用规模变大、数据量变多,仓库中的 First-DB-App 提供了另一条路径——现代浏览器内置的IndexedDB,它支持事务、索引和更大的存储容量。Notes App 使用 localStorage 即可,但读完该文档后可以自行对比两者的取舍(容量、复杂度、查询能力等)。
四、功能实现:创建、编辑、删除
4.1 创建笔记
用户输入标题与内容后,将新笔记push进数组并持久化:
function createNote(title, content) { const note = { id: Date.now().toString(), // 简单生成唯一 id title, content, createdAt: new Date().toISOString() }; notes.push(note); saveNotes(notes); renderNotes(); }4.2 编辑笔记
编辑通常由"点击笔记 → 进入编辑状态 → 保存回写"构成,核心是按id找到目标并更新字段:
function updateNote(id, title, content) { const note = notes.find(n => n.id === id); if (note) { note.title = title; note.content = content; saveNotes(notes); renderNotes(); } }4.3 删除笔记
删除时用filter生成不包含目标 id 的新数组,再整体覆盖存储:
function deleteNote(id) { notes = notes.filter(n => n.id !== id); saveNotes(notes); renderNotes(); }4.4 界面渲染
每次数据变化后重新渲染列表即可保持界面与存储一致。一个典型的渲染方式是为每条笔记创建独立的卡片节点,并为其中的"编辑""删除"按钮绑定对应处理函数。注意:渲染完成后所有事件监听都重新绑定,避免对旧节点的重复引用。
五、关键验收点:浏览器关闭后数据恢复
第四条 User Story 是验收重点,实现要点有两个:
- 应用启动时恢复数据:在页面加载完成(如
DOMContentLoaded)后执行一次localStorage.getItem('notes'),若存在则解析并渲染; - 每次数据变更即写回:创建、编辑、删除三个操作完成后都调用
saveNotes(),保证任何时刻关闭浏览器,最新状态都已落盘。
window.addEventListener('DOMContentLoaded', () => { const raw = localStorage.getItem('notes'); notes = raw ? JSON.parse(raw) : []; renderNotes(); });验证方式很简单:完成一次创建后刷新页面或直接关闭浏览器重新打开,若笔记仍在,即代表第四条故事达成。需要注意的是JSON.parse可能抛错(例如存储被外部修改或清空),生产级实现应加 try/catch 保护。
六、进阶功能一:Markdown 编辑与渲染
原文档 Bonus features 第一条要求:
User can create and edit a note in Markdown format. On save it will convert Markdown to HTML.
即用户以 Markdown 语法书写正文,保存时把 Markdown 转换成 HTML 显示。原文档推荐了两个资源:
- Markdown Guide 基础语法文档:学习标题、列表、代码块、强调等标准语法;
- marked:一个轻量的 Markdown 解析库,可直接把 Markdown 字符串转成 HTML。
典型实现:编辑模式下<textarea>里保留 Markdown 源码,预览模式下把源码交给 marked 渲染:
// 引入 marked 后,保存/预览时调用 function renderMarkdown(source) { return marked.parse(source); } // 预览区渲染 preview.innerHTML = renderMarkdown(note.content);使用第三方解析库时需注意XSS 风险:innerHTML直接插入用户输入前,建议对marked.parse()的输出做必要的 HTML 转义或使用安全的 sanitize 方案;同时,存储层仍然保存 Markdown 源码,只在展示层做转换,这样以后切换渲染器也不影响既有数据。
七、进阶功能二:显示笔记创建日期
Bonus features 第二条要求展示笔记创建时间:
User can see the date when he created the note
在 4.1 创建笔记 的数据模型中已经预留了createdAt字段,渲染时将其格式化为易读的日期文本即可:
function formatDate(isoString) { return new Date(isoString).toLocaleString(); // 例如 2026/9/30 00:42:04 }若只展示日期不显示时间,可改用toLocaleDateString()。这里的关键设计决策是:创建时用toISOString()保存标准时间戳,展示时才做本地化格式化,避免因浏览器时区差异导致存储数据混乱。
八、完整验收清单
对照原文档,一个达标的 Notes App 应满足:
| 类别 | 检查项 | 状态 |
|---|---|---|
| 必做 | 用户可以创建一条笔记 | ☐ |
| 必做 | 用户可以编辑一条笔记 | ☐ |
| 必做 | 用户可以删除一条笔记 | ☐ |
| 必做 | 关闭浏览器后笔记保留,再次打开可恢复 | ☐ |
| 加分 | 支持 Markdown 编辑,保存时转换为 HTML | ☐ |
| 加分 | 界面展示笔记创建日期 | ☐ |
九、资源与参考项目(源自原文档)
原文档列出的可用资源如下,均为实现本项目所需的核心资料:
- localStorage API:MDN 的 Window.localStorage 文档,涵盖 setItem / getItem / removeItem 等全部方法;
- Markdown Guide:Markdown 基础语法速查,编写笔记内容时的格式参考;
- marked:Markdown 解析库,用于进阶功能中的语法转换。
同时原文档提供了若干示例项目供参考(建议先自行实现再对照查看):
- 基于Angular在 Codepen 上实现的 Markdown 记事本;
- 基于React实现的 Markdown 记事本;
- 基于Angular 7 + Bootstrap 4实现的 Markdown 记事本。
这些示例展示了同一功能在不同框架下的组织方式,可作为后续把纯 JS 版本迁移到框架版时的学习素材。
十、与仓库其他项目的衔接
Notes App 位于 Projects/1-Beginner 目录下,与同目录的 Key-Value-App、First-DB-App 等组成了一条循序渐进的学习路径:
- Key-Value App锻炼键盘事件与界面状态联动;
- Notes App锻炼 CRUD 逻辑与 localStorage 持久化;
- First-DB-App将持久化升级为 IndexedDB 数据库方案,适合在 Notes App 之后继续挑战。
如需向仓库提交自己的实现或新的应用创意,可参照 Example Guide.md 的模板结构与 CONTRIBUTING.md 的贡献规范。
小结:Notes App 是一个"麻雀虽小、五脏俱全"的入门项目——增删改逻辑练手、localStorage 解决持久化、marked 引入 Markdown 渲染,三个知识点串起一个完整体验。按本文的分步实现与验收清单逐项推进,你就能得到一个可长期使用、可继续扩展(如搜索、分类、标签、导出)的个人在线记事本。
- 文档
- 教程
【免费下载链接】app-ideas
A Collection of application ideas which can be used to improve your coding skills.
相关推荐
app-ideas 实战指南:从零构建一个带 localStorage 持久化的 To-Do App(2-Intermediate)
app ideas 实战指南:从零构建一个带 localStorage 持久化的 To Do App(2 Intermediate) 导读 本文以 app id
文档教程ToolJet 事件操作实战:使用 Set localStorage 操作实现浏览器本地数据持久化
ToolJet 事件操作实战:使用 Set localStorage 操作实现浏览器本地数据持久化 导读 本文深入讲解 ToolJet 应用构建器中 Set l
低代码后端前端AI 应用MCP 服务Kudo's Slackbot 实战指南:用 Slack 斜杠命令打造可持久化的队友认可系统(app-ideas 3-Advanced)
Kudo's Slackbot 实战指南:用 Slack 斜杠命令打造可持久化的队友认可系统(app ideas 3 Advanced) 在团队协作中,一句真诚
文档教程
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考