Skip to content

本地存储(数据持久化)

18.1 localStorage 永久存储

localStorage 是浏览器提供的一种本地存储机制,用于在用户的浏览器中存储数据,数据会永久保存,即使关闭浏览器后再打开,数据仍然存在。

特点

  • 存储容量较大,通常为 5MB
  • 数据持久保存,不会自动过期
  • 只能存储字符串类型的数据
  • 同源策略限制,只能在同一域名下访问

基本操作

javascript
// 存储数据
localStorage.setItem("key", "value");

// 获取数据
const value = localStorage.getItem("key");
console.log(value); // 输出:value

// 删除数据
localStorage.removeItem("key");

// 清空所有数据
localStorage.clear();

// 获取存储的键名
const keys = Object.keys(localStorage);
console.log(keys);

// 获取存储的数量
const length = localStorage.length;
console.log(length);

18.2 sessionStorage 临时存储

sessionStoragelocalStorage 类似,但数据只在当前会话中有效,当关闭浏览器标签页或窗口时,数据会被清除。

特点

  • 存储容量较大,通常为 5MB
  • 数据只在当前会话中有效
  • 只能存储字符串类型的数据
  • 同源策略限制,只能在同一域名下访问

基本操作

javascript
// 存储数据
sessionStorage.setItem("key", "value");

// 获取数据
const value = sessionStorage.getItem("key");
console.log(value); // 输出:value

// 删除数据
sessionStorage.removeItem("key");

// 清空所有数据
sessionStorage.clear();

// 获取存储的键名
const keys = Object.keys(sessionStorage);
console.log(keys);

// 获取存储的数量
const length = sessionStorage.length;
console.log(length);

18.3 存储 / 获取 / 删除数据

存储对象和数组

由于 localStoragesessionStorage 只能存储字符串,我们需要使用 JSON.stringify() 将对象和数组转换为字符串,使用 JSON.parse() 将字符串转换回对象和数组。

javascript
// 存储对象
const user = {
  name: "张三",
  age: 25,
  email: "zhangsan@example.com"
};
localStorage.setItem("user", JSON.stringify(user));

// 获取对象
const storedUser = JSON.parse(localStorage.getItem("user"));
console.log(storedUser.name); // 输出:张三

// 存储数组
const todos = ["学习 JavaScript", "练习编程", "完成项目"];
localStorage.setItem("todos", JSON.stringify(todos));

// 获取数组
const storedTodos = JSON.parse(localStorage.getItem("todos"));
console.log(storedTodos[0]); // 输出:学习 JavaScript

存储和获取数字

javascript
// 存储数字
const score = 95;
localStorage.setItem("score", score.toString()); // 转换为字符串

// 获取数字
const storedScore = parseInt(localStorage.getItem("score"));
console.log(storedScore); // 输出:95
console.log(typeof storedScore); // 输出:number

18.4 实战:记住用户名 / 购物车数据

实战 1:记住用户名

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>记住用户名</title>
  <style>
    .container {
      max-width: 400px;
      margin: 50px auto;
      padding: 20px;
      border: 1px solid #ddd;
      border-radius: 8px;
      box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
    }
    h2 {
      text-align: center;
      margin-bottom: 20px;
    }
    .form-group {
      margin-bottom: 15px;
    }
    label {
      display: block;
      margin-bottom: 5px;
      font-weight: bold;
    }
    input {
      width: 100%;
      padding: 10px;
      border: 1px solid #ddd;
      border-radius: 4px;
      font-size: 16px;
    }
    .checkbox-group {
      display: flex;
      align-items: center;
    }
    .checkbox-group input {
      width: auto;
      margin-right: 10px;
    }
    button {
      width: 100%;
      padding: 10px;
      background-color: #4CAF50;
      color: white;
      border: none;
      border-radius: 4px;
      font-size: 16px;
      cursor: pointer;
      margin-top: 20px;
    }
    button:hover {
      background-color: #45a049;
    }
    .message {
      margin-top: 20px;
      padding: 10px;
      background-color: #f0f0f0;
      border-radius: 4px;
      text-align: center;
    }
  </style>
</head>
<body>
  <div class="container">
    <h2>用户登录</h2>
    <form id="loginForm">
      <div class="form-group">
        <label for="username">用户名</label>
        <input type="text" id="username" name="username" placeholder="请输入用户名">
      </div>
      <div class="form-group">
        <label for="password">密码</label>
        <input type="password" id="password" name="password" placeholder="请输入密码">
      </div>
      <div class="form-group checkbox-group">
        <input type="checkbox" id="remember" name="remember">
        <label for="remember">记住用户名</label>
      </div>
      <button type="submit">登录</button>
    </form>
    <div class="message" id="message"></div>
  </div>

  <script>
    const form = document.getElementById("loginForm");
    const username = document.getElementById("username");
    const password = document.getElementById("password");
    const remember = document.getElementById("remember");
    const message = document.getElementById("message");

    // 页面加载时,从本地存储中获取用户名
    window.onload = function() {
      const storedUsername = localStorage.getItem("username");
      if (storedUsername) {
        username.value = storedUsername;
        remember.checked = true;
      }
    };

    // 表单提交事件
    form.addEventListener("submit", function(event) {
      event.preventDefault();
      
      const usernameValue = username.value.trim();
      const passwordValue = password.value;
      
      if (usernameValue && passwordValue) {
        // 模拟登录成功
        message.textContent = `登录成功,欢迎 ${usernameValue}!`;
        message.style.backgroundColor = "#d4edda";
        message.style.color = "#155724";
        
        // 如果勾选了记住用户名,存储到本地存储
        if (remember.checked) {
          localStorage.setItem("username", usernameValue);
        } else {
          localStorage.removeItem("username");
        }
        
        // 清空密码
        password.value = "";
      } else {
        message.textContent = "请输入用户名和密码";
        message.style.backgroundColor = "#f8d7da";
        message.style.color = "#721c24";
      }
    });
  </script>
</body>
</html>

实战 2:购物车数据

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>购物车示例</title>
  <style>
    * {
      box-sizing: border-box;
      margin: 0;
      padding: 0;
    }
    body {
      font-family: Arial, sans-serif;
      padding: 20px;
    }
    .container {
      max-width: 800px;
      margin: 0 auto;
    }
    h1 {
      text-align: center;
      margin-bottom: 30px;
    }
    .products {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
      gap: 20px;
      margin-bottom: 30px;
    }
    .product {
      border: 1px solid #ddd;
      border-radius: 8px;
      padding: 15px;
      text-align: center;
    }
    .product h3 {
      margin-bottom: 10px;
    }
    .product .price {
      font-size: 18px;
      font-weight: bold;
      color: #f44336;
      margin-bottom: 15px;
    }
    .product button {
      padding: 8px 16px;
      background-color: #4CAF50;
      color: white;
      border: none;
      border-radius: 4px;
      cursor: pointer;
    }
    .product button:hover {
      background-color: #45a049;
    }
    .cart {
      border: 1px solid #ddd;
      border-radius: 8px;
      padding: 20px;
    }
    .cart h2 {
      margin-bottom: 20px;
    }
    .cart-item {
      display: flex;
      justify-content: space-between;
      align-items: center;
      padding: 10px 0;
      border-bottom: 1px solid #eee;
    }
    .cart-item:last-child {
      border-bottom: none;
    }
    .cart-item .name {
      flex: 1;
    }
    .cart-item .price {
      margin: 0 20px;
    }
    .cart-item .quantity {
      margin: 0 20px;
    }
    .cart-item button {
      padding: 5px 10px;
      background-color: #f44336;
      color: white;
      border: none;
      border-radius: 4px;
      cursor: pointer;
    }
    .cart-item button:hover {
      background-color: #d32f2f;
    }
    .cart-total {
      margin-top: 20px;
      text-align: right;
      font-size: 18px;
      font-weight: bold;
    }
    .cart-empty {
      text-align: center;
      padding: 20px;
      color: #666;
    }
  </style>
</head>
<body>
  <div class="container">
    <h1>购物车示例</h1>
    
    <div class="products">
      <div class="product">
        <h3>商品 1</h3>
        <div class="price">¥100</div>
        <button onclick="addToCart('商品 1', 100)">加入购物车</button>
      </div>
      <div class="product">
        <h3>商品 2</h3>
        <div class="price">¥200</div>
        <button onclick="addToCart('商品 2', 200)">加入购物车</button>
      </div>
      <div class="product">
        <h3>商品 3</h3>
        <div class="price">¥150</div>
        <button onclick="addToCart('商品 3', 150)">加入购物车</button>
      </div>
      <div class="product">
        <h3>商品 4</h3>
        <div class="price">¥300</div>
        <button onclick="addToCart('商品 4', 300)">加入购物车</button>
      </div>
    </div>
    
    <div class="cart">
      <h2>购物车</h2>
      <div id="cartItems"></div>
      <div class="cart-total" id="cartTotal">总计:¥0</div>
    </div>
  </div>

  <script>
    // 从本地存储中获取购物车数据
    function getCart() {
      const cart = localStorage.getItem("cart");
      return cart ? JSON.parse(cart) : [];
    }

    // 保存购物车数据到本地存储
    function saveCart(cart) {
      localStorage.setItem("cart", JSON.stringify(cart));
    }

    // 添加商品到购物车
    function addToCart(name, price) {
      const cart = getCart();
      
      // 检查商品是否已在购物车中
      const existingItem = cart.find(item => item.name === name);
      
      if (existingItem) {
        // 如果商品已存在,增加数量
        existingItem.quantity++;
      } else {
        // 如果商品不存在,添加新商品
        cart.push({ name, price, quantity: 1 });
      }
      
      saveCart(cart);
      updateCartUI();
    }

    // 从购物车中删除商品
    function removeFromCart(name) {
      const cart = getCart();
      const updatedCart = cart.filter(item => item.name !== name);
      saveCart(updatedCart);
      updateCartUI();
    }

    // 更新购物车 UI
    function updateCartUI() {
      const cart = getCart();
      const cartItems = document.getElementById("cartItems");
      const cartTotal = document.getElementById("cartTotal");
      
      if (cart.length === 0) {
        cartItems.innerHTML = '<div class="cart-empty">购物车为空</div>';
        cartTotal.textContent = "总计:¥0";
        return;
      }
      
      let html = '';
      let total = 0;
      
      cart.forEach(item => {
        const itemTotal = item.price * item.quantity;
        total += itemTotal;
        html += `
          <div class="cart-item">
            <div class="name">${item.name}</div>
            <div class="price">¥${item.price}</div>
            <div class="quantity">×${item.quantity}</div>
            <div class="item-total">¥${itemTotal}</div>
            <button onclick="removeFromCart('${item.name}')">删除</button>
          </div>
        `;
      });
      
      cartItems.innerHTML = html;
      cartTotal.textContent = `总计:¥${total}`;
    }

    // 页面加载时更新购物车 UI
    window.onload = function() {
      updateCartUI();
    };
  </script>
</body>
</html>

小结

  • localStorage:永久存储,数据不会自动过期
  • sessionStorage:临时存储,数据在会话结束后清除
  • 两者都只能存储字符串类型的数据,需要使用 JSON.stringify()JSON.parse() 处理对象和数组
  • 存储容量通常为 5MB
  • 遵循同源策略,只能在同一域名下访问
  • 本地存储在网页开发中常用于:
    • 记住用户偏好设置
    • 存储购物车数据
    • 缓存用户数据
    • 实现离线应用
  • 注意不要存储敏感信息,因为本地存储是明文存储的

© 2026 编程马·菜鸟教程 版权所有