网站

Web Storage API | MDN

Window.localStorage | MDN

Window.sessionStorage | MDN

引入

网页关闭后,JS 变量里的数据就全丢了。如果想让数据在页面关闭后仍然保留,就需要把数据存到浏览器里。

localStoragesessionStorage 就是浏览器提供的本地存储方案。

正文

定义

定义

Web Storage 是浏览器提供的本地存储 API,可以在浏览器中保存键值对数据。分为 localStorage(永久存储)和 sessionStorage(会话存储)两种。

localStorage

localStorage 里的数据会一直保留,直到手动清除。关闭浏览器、关闭电脑,数据还在。

localStorage.setItem("userName", "张三");
 
console.log(localStorage.getItem("userName"));

输出 "张三",即使刷新页面或重启浏览器,数据依然存在。

sessionStorage

sessionStorage 里的数据只在当前标签页存活。标签页关闭后,数据自动清除。

sessionStorage.setItem("token", "abc123");
 
console.log(sessionStorage.getItem("token"));

刷新页面数据还在,但关闭标签页后数据就没了。

常用方法

localStoragesessionStorage 的方法完全一样。

方法作用
setItem(key, value)存储数据(键值对)
getItem(key)读取数据
removeItem(key)删除指定数据
clear()清空所有数据
key(index)获取指定位置的键名
length存储数据的条数

存储数据

localStorage.setItem("name", "张三");
localStorage.setItem("age", "25");

读取数据

const name = localStorage.getItem("name");
const age = localStorage.getItem("age");
 
console.log(name);
console.log(age);

如果键不存在,getItem() 返回 null

删除数据

localStorage.removeItem("name");

清空所有数据

localStorage.clear();

也可以像对象一样操作

localStoragesessionStorage 支持点语法或方括号语法。

localStorage.userName = "张三";
 
console.log(localStorage.userName);
 
delete localStorage.userName;

不过推荐用 setItem() / getItem(),写法更明确,不容易出错。

只能存储字符串

Web Storage 只能存储字符串。如果存入数字或布尔值,会自动转成字符串。

localStorage.setItem("count", 100);
 
console.log(typeof localStorage.getItem("count"));

输出 "string",数字 100 被转成了字符串 "100"

存储对象

要存储对象或数组,需要先用 JSON.stringify() 转成字符串,取出时再用 JSON.parse() 转回来。

存储对象

const user = {
  name: "张三",
  age: 25,
  hobby: "编程"
};
 
localStorage.setItem("user", JSON.stringify(user));

读取对象

const data = localStorage.getItem("user");
const user = JSON.parse(data);
 
console.log(user.name);
console.log(user.age);

JSON.stringify() 把对象转成 JSON 字符串,JSON.parse() 把 JSON 字符串转回对象。

存储数组

const todos = ["学习 JS", "写笔记", "做练习"];
 
localStorage.setItem("todos", JSON.stringify(todos));
const data = localStorage.getItem("todos");
const todos = JSON.parse(data);
 
console.log(todos[0]);

例子

记住用户名

<input id="userName" type="text" placeholder="用户名">
<label>
  <input id="remember" type="checkbox"> 记住我
</label>
<button id="loginBtn">登录</button>
const userName = document.querySelector("#userName");
const remember = document.querySelector("#remember");
const loginBtn = document.querySelector("#loginBtn");
 
const saved = localStorage.getItem("savedUserName");
if (saved) {
  userName.value = saved;
  remember.checked = true;
}
 
loginBtn.addEventListener("click", function () {
  if (remember.checked) {
    localStorage.setItem("savedUserName", userName.value);
  } else {
    localStorage.removeItem("savedUserName");
  }
  console.log("登录:" + userName.value);
});

页面加载时检查是否有保存的用户名,有的话自动填充。

保存待办列表

<input id="input" type="text" placeholder="添加待办">
<button id="addBtn">添加</button>
<ul id="list"></ul>
const input = document.querySelector("#input");
const addBtn = document.querySelector("#addBtn");
const list = document.querySelector("#list");
 
let todos = JSON.parse(localStorage.getItem("todos")) || [];
 
function render() {
  list.innerHTML = "";
  todos.forEach(function (item, index) {
    const li = document.createElement("li");
    li.textContent = item;
    list.appendChild(li);
  });
  localStorage.setItem("todos", JSON.stringify(todos));
}
 
addBtn.addEventListener("click", function () {
  if (input.value === "") {
    return;
  }
  todos.push(input.value);
  input.value = "";
  render();
});
 
render();

待办列表保存在 localStorage,刷新页面后数据不会丢失。

保存用户偏好

<button id="themeBtn">切换主题</button>
const themeBtn = document.querySelector("#themeBtn");
const savedTheme = localStorage.getItem("theme");
 
if (savedTheme === "dark") {
  document.body.classList.add("dark");
}
 
themeBtn.addEventListener("click", function () {
  document.body.classList.toggle("dark");
  const isDark = document.body.classList.contains("dark");
  localStorage.setItem("theme", isDark ? "dark" : "light");
});

存储限制

  • 每个域名的存储容量大约是 5MB
  • 超出容量时,setItem() 会抛出 QuotaExceededError 错误
  • 不同域名的存储是独立的,互不影响
try {
  localStorage.setItem("bigData", hugeString);
} catch (error) {
  console.log("存储空间不足:" + error.message);
}

三种存储方式对比

对比localStoragesessionStoragecookie
容量~5MB~5MB~4KB
有效期永久,需手动清除标签页关闭时清除可设置过期时间
是否发送服务器不会不会每次请求自动带上
跨标签页共享同域共享不共享同域共享
数据类型字符串字符串字符串
是否可被 JS 读取可设置 HttpOnly 禁止 JS 读取
  • localStorage:适合存用户偏好、主题设置、不需要发送到服务器的数据
  • sessionStorage:适合存临时数据,比如多步表单的中间步骤
  • cookie:适合存需要发送到服务器的数据,比如登录状态(session ID)

常见写法

写法作用
localStorage.setItem("key", "value")存储数据
localStorage.getItem("key")读取数据
localStorage.removeItem("key")删除数据
localStorage.clear()清空所有数据
JSON.stringify(obj)对象转字符串
JSON.parse(str)字符串转对象

特点

  • localStoragesessionStorage 用法完全一样,区别在于生命周期
  • 只能存储字符串,存对象要先 JSON.stringify(),取出来要 JSON.parse()
  • 数据只存在客户端,不会自动发送到服务器
  • 同一个域名下的数据是共享的(localStorage)或按标签页隔离(sessionStorage
  • 存储容量大约 5MB,超出会报错
  • 用户可以在浏览器开发者工具中查看和修改本地存储的数据

注意事项

  • getItem() 读取不存在的键会返回 nullJSON.parse(null) 会报错,需要判断
  • 不要把敏感信息(密码、token)存在 localStorage 里,容易被 XSS 攻击读取
  • sessionStorage 只在一个标签页有效,打开新标签页不会继承数据
  • clear() 会删除当前域名下所有存储数据,慎用
  • 不同浏览器、不同设备上的本地存储不互通

理解

可以把 localStorage 理解成浏览器里的一个”小笔记本”。

JS 把数据写到笔记本里,即使关掉浏览器,笔记本还在,下次打开可以继续读。

sessionStorage 则是一张”便签纸”,用完就扔,关掉标签页就没了。

我理解本地存储的重点是:setItem() 写数据,用 getItem() 读数据,存对象要先 JSON.stringify()

引出

掌握了本地存储之后,可以结合 JS AjaxJS JSON,实现完整的数据获取、处理和持久化流程。