JavaScript LocalStorage
什么是 LocalStorage?
LocalStorage 是 Web Storage API 的一部分,它允许网页在用户浏览器中存储键值对数据,并且没有过期时间。这意味着即使用户关闭浏览器或重启计算机,存储的数据也不会被删除,除非通过 JavaScript 代码明确地删除或用户清除浏览器数据。
与传统的 Cookie 相比,LocalStorage 具有以下优势:
- 存储容量更大:LocalStorage 通常可以存储约 5-10MB 的数据(取决于浏览器),而 Cookie 仅限于 4KB。
- 不会随请求发送到服务器:存储在 LocalStorage 中的数据不会在每次 HTTP 请求时发送到服务器,减少了网络流量。
- 更简单的 API:LocalStorage 提供了简单直观的方法来存储和检索数据。
LocalStorage 是同源的,这意味着它只能被来自相同协议、主机名和端口的页面访问。
LocalStorage 的基本操作
1. 存储数据
使用 localStorage.setItem()
方法存储数据:
// 语法:localStorage.setItem(key, value);
localStorage.setItem('username', 'John');
localStorage.setItem('isLoggedIn', 'true');
localStorage.setItem('userPreferences', JSON.stringify({ theme: 'dark', fontSize: 16 }));
LocalStorage 只能存储字符串。如果你需要存储对象或数组,必须先使用 JSON.stringify()
将其转换为字符串。
2. 检索数据
使用 localStorage.getItem()
方法检索数据:
// 语法:localStorage.getItem(key);
const username = localStorage.getItem('username');
console.log(username); // 输出: John
const isLoggedIn = localStorage.getItem('isLoggedIn');
console.log(isLoggedIn); // 输出: "true" (注意:这是字符串,不是布尔值)
const userPreferences = JSON.parse(localStorage.getItem('userPreferences'));
console.log(userPreferences); // 输出: { theme: "dark", fontSize: 16 }
3. 更新数据
要更新已存在的数据,只需使用相同的键再次调用 setItem()
:
// 更新现有数据
localStorage.setItem('username', 'Jane'); // 用户名从 John 更新为 Jane
// 更新对象数据
const userPrefs = JSON.parse(localStorage.getItem('userPreferences'));
userPrefs.theme = 'light';
localStorage.setItem('userPreferences', JSON.stringify(userPrefs));
4. 删除数据
使用 localStorage.removeItem()
方法删除特定键的数据:
// 删除单个项
localStorage.removeItem('username');
要删除所有数据,使用 localStorage.clear()
方法:
// 清空所有 localStorage 数据
localStorage.clear();
5. 检查存储中的键数量
使用 localStorage.length
属性获取存储中的键数量:
const itemCount = localStorage.length;
console.log(`LocalStorage 中有 ${itemCount} 个项`);
6. 遍历所有存储项
可以使用 key()
方法遍历 LocalStorage 中的所有项:
// 遍历所有存储项
for (let i = 0; i < localStorage.length; i++) {
const key = localStorage.key(i);
const value = localStorage.getItem(key);
console.log(`${key}: ${value}`);
}
使用 LocalStorage 的实际案例
案例 1:用户首选项存储
下面是一个保存用户主题首选项的简单示例:
// 主题切换功能
function setTheme(themeName) {
// 保存首选项到 localStorage
localStorage.setItem('theme', themeName);
// 应用主题
document.body.className = themeName;
}
function loadTheme() {
// 检查是否存在已保存的主题
const savedTheme = localStorage.getItem('theme');
if (savedTheme) {
// 如果有保存的主题,应用它
document.body.className = savedTheme;
} else {
// 默认主题
document.body.className = 'light-theme';
}
}
// 页面加载时初始化主题
document.addEventListener('DOMContentLoaded', loadTheme);
// 主题切换按钮
document.getElementById('theme-toggle').addEventListener('click', function() {
const currentTheme = localStorage.getItem('theme') || 'light-theme';
const newTheme = currentTheme === 'light-theme' ? 'dark-theme' : 'light-theme';
setTheme(newTheme);
});
案例 2:简单的待办事项应用
一个使用 LocalStorage 存储待办事项的简单应用:
// 待办事项应用
const todoApp = {
todos: [],
// 初始化
init: function() {
this.loadTodos();
this.render();
this.setupEventListeners();
},
// 从 LocalStorage 加载待办事项
loadTodos: function() {
const savedTodos = localStorage.getItem('todos');
this.todos = savedTodos ? JSON.parse(savedTodos) : [];
},
// 保存待办事项到 LocalStorage
saveTodos: function() {
localStorage.setItem('todos', JSON.stringify(this.todos));
},
// 添加新的待办事项
addTodo: function(text) {
this.todos.push({
id: Date.now(),
text: text,
completed: false
});
this.saveTodos();
this.render();
},
// 切换待办事项的完成状态
toggleTodo: function(id) {
this.todos = this.todos.map(todo => {
if (todo.id === id) {
return { ...todo, completed: !todo.completed };
}
return todo;
});
this.saveTodos();
this.render();
},
// 删除待办事项
deleteTodo: function(id) {
this.todos = this.todos.filter(todo => todo.id !== id);
this.saveTodos();
this.render();
},
// 渲染待办事项列表
render: function() {
const todoList = document.getElementById('todo-list');
todoList.innerHTML = '';
this.todos.forEach(todo => {
const li = document.createElement('li');
li.innerHTML = `
<input type="checkbox" ${todo.completed ? 'checked' : ''} data-id="${todo.id}">
<span style="${todo.completed ? 'text-decoration: line-through' : ''}">
${todo.text}
</span>
<button data-id="${todo.id}" class="delete-btn">删除</button>
`;
todoList.appendChild(li);
});
},
// 设置事件监听器
setupEventListeners: function() {
const form = document.getElementById('todo-form');
const todoList = document.getElementById('todo-list');
form.addEventListener('submit', e => {
e.preventDefault();
const input = form.querySelector('input');
if (input.value.trim()) {
this.addTodo(input.value.trim());
input.value = '';
}
});
todoList.addEventListener('click', e => {
if (e.target.type === 'checkbox') {
this.toggleTodo(Number(e.target.dataset.id));
} else if (e.target.classList.contains('delete-btn')) {
this.deleteTodo(Number(e.target.dataset.id));
}
});
}
};
// 初始化待办事项应用
document.addEventListener('DOMContentLoaded', () => todoApp.init());
案例 3:网站访问计数器
使用 LocalStorage 创建一个简单的网站访问计数器:
function updateVisitCount() {
// 获取当前计数
let visits = localStorage.getItem('visitCount');
// 检查是否存在计数,不存在则初始化为0
if (!visits) {
visits = 0;
}
// 增加访问计数
visits = parseInt(visits) + 1;
// 保存新的计数
localStorage.setItem('visitCount', visits);
// 更新页面上的计数显示
document.getElementById('visit-counter').textContent = visits;
}
// 页面加载时调用
document.addEventListener('DOMContentLoaded', updateVisitCount);
LocalStorage 限制和注意事项
- 容量限制:通常为 5-10MB,具体取决于浏览器实现。
- 只能存储字符串:需要使用
JSON.stringify()
和JSON.parse()
来处理复杂数据结构。 - 同源策略:只能访问来自相同协议、主机和端口的页面的数据。
- 不支持过期:数据不会自动过期,必须手动删除。
- 同步操作:所有的读写操作都是同步的,可能会影响性能。
- 隐私模式:在浏览器的隐私/隐身模式下,一些浏览器会限制 LocalStorage 的访问或清除其数据。
调试 LocalStorage
在浏览器开发者工具中,你可以轻松查看和修改 LocalStorage 数据:
- 打开浏览器的开发者工具(F12 或 右键 → 检查)
- 导航到"应用程序"或"存储"选项卡
- 在左侧面板中展开"本地存储"并选择你的网站
- 查看、添加、编辑或删除键值对
总结
LocalStorage 是在浏览器中持久化存储数据的简单而强大的方法。它适用于存储用户首选项、表单数据、应用程序状态等不敏感的信息。与 Cookie 相比,它提供了更大的存储空间和更简单的 API,同时不会随 HTTP 请求一起发送到服务器。
记住以下关键点:
- 使用
setItem()
,getItem()
,removeItem()
和clear()
来管理数据 - 复杂数据结构需要使用 JSON 格式化
- 数据会持久存储,直到被明确删除
- 只能存储来自相同源的数据
通过合理利用 LocalStorage,你可以创建响应更快、体验更好的 Web 应用程序,减少对服务器的依赖。
练习
- 创建一个简单的笔记应用,允许用户添加、编辑和删除笔记,并将所有笔记保存在 LocalStorage 中。
- 实现一个网站主题切换器,让用户可以在深色和浅色模式之间切换,并在页面刷新后保持选择。
- 构建一个小型购物车功能,允许用户添加商品到购物车,并在页面刷新后保持购物车内容。
- 创建一个"最近查看"功能,记录用户最近查看过的5个项目,并在他们返回网站时显示这些项目。