看完秒变大佬的localStorage用法与特性

970 阅读5分钟

引言

我们的目标是创建一个可以添加和显示待办事项的计划书,并且这些事项能够被持久地保存下来,即使用户刷新页面或关闭浏览器后再次访问,也能看到之前添加过的项目。为了达到这个目的,我们将使用HTML5中的localStorage来处理数据的存取。

1734180596454.gif

localStorage

在Web开发中,用户数据的持久化是一个关键需求。传统的做法是将所有数据保存到服务器端数据库,但随着HTML5的推出,开发者有了新的选择——localStorage。浏览器开辟了5Mb左右的存储空间作为localStorage,它允许我们直接在用户的浏览器中存储数据,无需依赖服务器,从而为构建快速响应的应用提供了便利。localStorage 对象提供了几个方法用于操作存储的数据:

  1. setItem(keyName, keyValue):用来保存数据到 localStorage 中。 参数 keyName 是你想要创建的键名,keyValue 是你想要存储的值。

  2. getItem(keyName): 用来从 localStorage 中读取指定键名的数据。 参数 keyName 是你要查找的键名,返回与之关联的值;如果找不到,则返回 null

  3. removeItem(keyName): 用来从 localStorage 中移除指定键名的数据。 参数 keyName 是要删除的键名。

  4. clear(): 清空 localStorage 中的所有数据。

HTML结构设计和CSS样式

首先,我们定义了基本的HTML文档结构,包括标题、表单用于输入新事项以及一个无序列表(<ul>)用来展示已有的事项:

HTML代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no, viewport-fit=cover">
    <title>LocalStorage</title>
    <link rel="stylesheet" href="styles.css">
</head>
<body>
    <div class="wrapper">
        <h2>PROPOSAL</h2>
        <ul class="plates">
            <li>Loading...</li>
        </ul>
        <form class="add-items">
            <!-- required 必填 -->
            <input type="text" name="item" placeholder="Item Name" required>
            <input type="submit" value="+ Add Item">
        </form>
    </div>
    <script src="app.js"></script>
</body>
</html>

这里,我们通过<meta name="viewport">确保了页面在移动设备上的良好显示效果,同时设置了禁止缩放以优化用户体验。

CSS代码

接下来,我们为应用添加了一些基础的CSS样式,下面是我在本例中使用的CSS代码

/* styles.css */
* {
    margin: 0;
    padding: 0;
}

html {
    box-sizing: border-box;
    background: url('http://wes.io/hx9M/oh-la-la.jpg') center no-repeat;
    background-size: cover;
    min-height: 100vh;
    display: flex;
    justify-content: center;
    align-items: center;
    text-align: center;
    font-family: Futura,"Trebuchet MS",Arial,sans-serif;
}

*, *:before, *:after {
    box-sizing: inherit; 
}

.wrapper {
    padding: 20px;
    max-width: 350px;
    background: rgba(255,255,255,0.95);
    box-shadow: 0 0 0 10px rgba(0,0,0,0.1);
}

h2 {
    text-align: center;
    margin: 0;
    font-weight: 200;
}

.plates {
    margin: 0;
    padding: 0;
    text-align: left;
    list-style: none;
}

.plates li {
    border-bottom: 1px solid rgba(0,0,0,0.2);
    padding: 10px 0;
    font-weight: 100;
    display: flex;
}

.plates label {
    flex: 1;
    cursor: pointer;
}

.plates input {
    display: none;
}

.plates input + label:before {
    content: '⬜';
    margin-right: 10px;
}

.plates input:checked + label:before {
    /* 选中标志 */
    content: '🌮';   
}

.add-items {
    margin-top: 20px;
}

.add-items input {
    padding: 10px;
    outline: 0;
    border: 1px solid rgba(0,0,0,0.1);
}

我们先来看一下结果

image.png

JS逻辑实现

最后,也是最重要的一环,就是JS代码的编写。以下是完整的JS代码:

const addItems = document.querySelector('.add-items'); // form
const itemsList = document.querySelector('.plates');  // ul
// 每次刷新后先获取localStorage中内容,如果没有为 [ ]
const items =JSON.parse(localStorage.getItem("items"))|| [];
// 添加plate item
function addItem(event){
    event.preventDefault();   // 阻止默认行为 不要让它每次提交后都刷新
    console.log(this,event.target);  // this 指向form 
    // 性能
    const text = (this.querySelector('[name=item]')).value.trim();  // 输入的内容    querySelector 属于任何一个元素  缩小了范围 速度快
    // 数据
    const item={
        // text:text,
        text,  // es6
        done:false,   
        }
    items.push(item);
    populateList(items,itemsList);
    localStorage.setItem('items',JSON.stringify(items));
    this.reset(); // 清空表单
    }
// 渲染ul
function populateList(items, platesList){
    platesList.innerHTML = items.map((plate,i)=>{
    return `
        <li>
        <input 
         type="checkbox" 
         data-index=${i} 
         id="item${i}"
         ${plate.done?'checked':''}
        >
        <label for="item${i}">${plate.text}</label>
        </li>
        `
        }).join('')
}
addItems.addEventListener('submit',addItem);
populateList(items,itemsList);

至此,已经实现了我们想要的功能,下面我们来简单解释一下这段代码。

在这段代码中,我们做了以下几件事:

  1. 初始化:当DOM加载完成后,检查localStorage中是否有保存的数据,如果有,则解析成数组形式。
  2. 添加事项:先清除表单的默认行为。每当用户提交表单时,获取输入框中的文本内容,创建一个新的事项对象,并将其添加到items数组中。然后调用populateList函数重新渲染列表,并将最新的items数组序列化后存入localStorage
  3. 渲染列表populateList函数根据当前的items数组生成对应的HTML片段,并插入到.plates元素内。
  4. 清空表单:每次成功添加事项后,自动清空表单输入框,准备下一次输入,优化体验。

我们可以在浏览器中的开发者工具下的Application中的Local storage找到你存储的内容 image.png

localStorage、sessionStorage、Cookie之间的区别

localStoragesessionStorageCookie 是Web开发中用于在客户端存储数据的三种机制。它们各有特点,适用于不同的应用场景。下面我们将使用一个表格来比较它们之间的区别。

特性localStoragesessionStorageCookie
数据持久性永久保存,除非手动清除仅在当前会话期间有效,关闭标签页后清除可设置过期时间;默认为会话结束时清除
存储容量每个域名约5MB每个域名约5MB单个4KB左右,域名下总计不超过4KB到8KB
数据发送方式不随HTTP请求自动发送不随HTTP请求自动发送每次HTTP请求都会携带
安全性不参与HTTP请求,相对更安全(但仍需防范XSS)同上可通过HttpOnlySecure增强安全性
适用场景需要长期保存的非敏感数据短暂会话内的临时数据身份验证、跟踪用户行为等需要与服务器交互的数据

y9SdQ8jAibP26z1.jpg

总结

localStorage虽然有其局限性(例如存储容量有限),但在许多场景下已经足够满足需求,特别是在不需要频繁与服务器通信的情况下。希望这篇文章能为你理解和应用localStorage提供有价值的参考。