通过构建笔记应用程序学习存储 API

2025-06-07

通过构建笔记应用程序学习存储 API

让我们window.localStorage通过用一些简单的 HTML、CSS 和 JavaScript 构建一个小型笔记应用来学习。我们将编写一个小型 UI,并自动将用户的笔记保存到浏览器中。我的同事把他所有的代码片段都保存在类似这样的应用里。我真不敢相信他只用 50-60 行代码就实现了如此大的成果!

过去,大多数客户端存储交互都涉及操作 Cookie,但幸运的是,我们现在有了现代 API。使用 Cookie 时,用户每次请求都会发送存储的所有内容,这意味着双方的性能都会下降。

输入:localStorage。对象上可用的键/值 API windowsessionStorage与页面会话期间有效的 API 不同,localStorage它没有过期时间。

所有键和值都会转换为字符串。让我们添加、更新和删除一个键,然后尝试从空键读取数据。这是控制台输入,因此返回值会跟随命令。

// Add key - or overwrite existing key
window.localStorage.setItem('foo', 'bar')
> undefined

// Read a value from a key
window.localStorage.getItem('foo')
> "bar"

// Delete key - deleting empty yields same return value
window.localStorage.removeItem('foo')
> undefined

// Read from a deleted or unknown key
window.localStorage.getItem('foo')
> null
Enter fullscreen mode Exit fullscreen mode

与 localStorage 交互的其他方式包括清除所有键并遍历现有键。

// Get the read-only length
window.localStorage.length
> 6

// Get the nth key
window.localStorage.key(0)
> "algoliasearch-client-js"

// Delete all keys
window.localStorage.clear()
> undefined

// Iterate through all keys
for (let i = 0; i < window.localStorage.length; i++) {
    console.log(window.localStorage.key(i));
}
Enter fullscreen mode Exit fullscreen mode

您可以在此处的开发者控制台中尝试其中一些功能。DEV 会在我写作时为我存储以下 localStorage 键。请确保不要删除其中任何一个!algoliasearch-client-js, config_body_class, current_user, https://dev.to/new, pusherTransportTLS

应用程序

这就是我们要做的。一个小巧实用的笔记应用。除了间距之外,它几乎不使用任何样式(发送拉取请求)。重要的是应用如何与客户端浏览器存储进行通信。

希望你已经想好了localStorage我们需要的方法。让我们使用一个现成的 HTML 模板,其中定义了我们将要使用的函数。

<h5>Tiny Note Taker</h5>
<div>
    <button onclick="newNote()">New</button>
        <select id="notes" onchange="changeNote()"></select>
        <button onclick="deleteNote()">Delete</button>
</div>
<textarea id="editor" rows="10" onkeyup="saveNote()"
    onkeydown="checkEmpty()" autofocus></textarea>
<script src="./index.js"></script>
Enter fullscreen mode Exit fullscreen mode

花一点时间思考一下这些函数与我们刚才看到的存储方法有何关系,以及它们如何操作 DOM。


newNote()提示用户输入注释名称并创建它。

changeNote()当选定元素发生改变时,切换到新注释。

deleteNote()删除当前选定的注释。

saveNote()按用户类型保存当前选定的注释。

checkEmpty()— 这一点不太明显。

如果用户到达页面并在创建新笔记之前开始输入,则名称将为""空字符串。相反,在他们输入内容但在保存笔记之前,将当前笔记命名为untitled。我们在此简化逻辑,将其分为两个事件。onkeydown检查笔记是否为空,并在必要时进行修复。这意味着onkeyup可以直接保存笔记,而无需进行任何其他检查。因此,checkEmpty()

提醒:关键事件几乎总是按此顺序调用onkeydown -> onkeypress -> onkeyup,并且它们都有自己的位置!

让我们从基本情况开始。在用户输入时保存一条注释。由于我们将脚本包含放在了 HTML 的底部,因此我们可以获取所需两个元素的引用,而无需等待任何文档加载事件。

const notes = document.querySelector('#notes');
const editor = document.querySelector('#editor');
Enter fullscreen mode Exit fullscreen mode

太好了。这些引用将持续存在于此脚本的整个生命周期内,因为我们永远不会删除这些元素。接下来,如果用户在输入时没有先点击“新建”按钮,我们需要将空名称的笔记标题设置为“无标题”。

/**
 * Check for empty note title.
 */
function checkEmpty() {
    if (notes.length === 0) {
        const untitled = document.createElement('option');
        untitled.innerText = 'untitled';
        notes.appendChild(untitled);
    }
}
Enter fullscreen mode Exit fullscreen mode

这里我们用 JavaScript 创建了一个 option 元素,并将其添加到下拉列表中。我们暂时不需要进行任何保存,保存操作将在几毫秒后,当用户将手指从当前按键上移开时进行。

几毫秒后。

/**
 * Save editor text to storage under the current note.
 */
function saveNote() {
    window.localStorage.setItem(notes.value, editor.value);
}
Enter fullscreen mode Exit fullscreen mode

就是这样localStorage.setItem!我们知道它的作用。它会将笔记文本保存为值,将笔记标题 ( "untitled") 保存为键。现在我们有一个问题需要解决。如果用户离开后再返回,下拉列表将为空。更糟糕的是:他们会覆盖自己的"untitled"笔记。

当我们的脚本运行时,在我们获取对这些元素的引用之后,让我们用所有用户保存的笔记填充选择下拉菜单。

const notes = document.querySelector('#notes');
const editor = document.querySelector('#editor');

// Load user's saved notes
for (let i = 0; i < window.localStorage.length; i++) {
    const newNote = document.createElement('option');
    newNote.innerText = window.localStorage.key(i);
    notes.appendChild(newNote);
}
changeNote();
Enter fullscreen mode Exit fullscreen mode

这里我们使用了 的只读length属性localStorage及其方法key()。所有已保存的笔记都会加载到下拉列表中。我们让 HTML 作为状态运行。这样,我们就不需要在 JavaScript 中跟踪任何笔记了。我们依靠简单的函数将 DOM 链接到存储 API。

在最后一段代码的底部,我们看到changeNote()它将当前选定的注释加载到 textarea 元素(即编辑器)中。在创建新注释后,也会调用此函数,以清除编辑器。新注释会使用空字符串进行初始化。

/**
 * Change editor text to the currently selected note.
 */
function changeNote() {
    editor.value = window.localStorage.getItem(notes.value);
}
Enter fullscreen mode Exit fullscreen mode

存储 API 为我们简化了繁重的工作。

用户需要一种命名和创建注释的方法。newNote()它就是这么做的。它使用Element#insertBefore将新注释放置在选择框的顶部。此方法在父元素上调用。var insertedNode = parentNode.insertBefore(newNode, referenceNode);此方法的巧妙之处在于它接受 null 值作为第二个参数。这意味着我们可以insertBefore在空的父元素上调用它!

/**
 * Ask the user to name their new note then create it.
 * Add this note to the select div then focus to it.
 */
function newNote() {
    const note = prompt('Name of note?');
    window.localStorage.setItem(note, '');

    const noteElem = document.createElement('option');
    noteElem.innerText = note;
    notes.insertBefore(noteElem, notes.firstChild);

    // Focus this note
    notes.value = note;
    changeNote();
}
Enter fullscreen mode Exit fullscreen mode

我们的笔记应用即将完成。最后一个需要的功能是删除笔记。当用户完成一条笔记后,他们可以选中它,然后点击“删除”按钮。这个功能最棘手的部分是在下拉菜单中找到要删除的笔记。使用 DOM 作为状态的缺点之一就是,我们必须循环遍历每个选项,检查value……

/**
 * Delete currently selected note
 */
function deleteNote() {
    const note = notes.value;
    window.localStorage.removeItem(note);
    editor.value = '';
    for (let i = 0; i < notes.length; i++) {
        const option = notes[i];
        if (option.value === note) {
            notes.removeChild(option);
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

现在,我们已经拥有一个功能齐全的笔记应用,并且可以通过 CDN 实现无限扩展。我们使用了强大的存储 API,并学习了如何将 DOM 用作应用状态。加油!🙌

请在此处查看最终的应用程序代码,并在此处查看实时版本


与 150 多名订阅我的关于编程和个人成长的新闻通讯的人一起!

我发布有关科技的推文@healeycodes

文章来源:https://dev.to/healeycodes/learn-the-storage-api-by-building-a-note-takeing-app-6h5
PREV
我的第一个 Golang 程序
NEXT
在 GitHub 上赢得“构建通过”徽章✅!使用 Travis CI 测试你的 Express 应用