一篇明白浏览器localStorage 、sessionStorage和 IndexedDB存储方式
localStorage 和 sessionStorage它们是现代浏览器提供的两种Web Storage API用于在用户的浏览器中本地存储键值对数据。它们比传统的Cookie更强大、更方便。核心共同点在讨论区别之前先了解它们的共同点存储类型都只能存储字符串。如果你想存储对象或数组需要使用JSON.stringify()转换后存入读取时用JSON.parse()解析。同源策略存储空间严格遵循同源策略。这意味着只有来自相同协议、域名、端口的页面才能访问同一份数据。API 相同它们使用完全相同的语法和方法学会一个就等于学会了另一个。仅限客户端数据只存储在客户端浏览器中不会随着每个HTTP请求发送到服务器不像Cookie。核心区别它们最根本的区别在于数据的生命周期存活时间和作用域谁可以访问。特性localStoragesessionStorage生命周期永久存储除非用户手动清除通过浏览器设置或代码否则数据会一直存在。会话期存储。数据只在当前浏览器标签页有效。关闭标签页数据就会被清除。作用域跨标签页共享。同一个网站下所有同源的标签页都可以共享和操作同一份localStorage数据。仅限当前标签页。每个标签页都有自己的sessionStorage即使是同一个页面在不同标签页中也是隔离的互不干扰。典型用例长期偏好设置如深色模式主题、购物车内容、用户登录令牌需注意安全性、需要离线访问的数据。一次性表单填写、单页应用SPA的临时状态管理、当前标签页的敏感操作如网银交易避免多标签页干扰。使用方法 (API)它们的API非常简单易用主要有以下几个方法1. 设置数据 (Set)使用setItem(key, value)方法。// 存储一个字符串localStorage.setItem(username,john_doe);sessionStorage.setItem(currentTabId,tab1);// 存储一个对象需要先转换成JSON字符串constuserSettings{theme:dark,language:zh-CN};localStorage.setItem(settings,JSON.stringify(userSettings));2. 获取数据 (Get)使用getItem(key)方法。// 获取字符串constusernamelocalStorage.getItem(username);// john_doe// 获取并解析对象constsettingsStrlocalStorage.getItem(settings);constsettingsObjJSON.parse(settingsStr);// { theme: dark, language: zh-CN }// 如果获取不存在的key会返回 nullconstnothinglocalStorage.getItem(nonexistent);// null3. 删除数据 (Remove)使用removeItem(key)方法删除特定的数据项。// 删除 username 这项数据localStorage.removeItem(username);4. 清空所有数据 (Clear)使用clear()方法会清空当前域名下的所有对应存储。// 慎用这会删除当前网站所有的 localStorage 数据而不是单个项。localStorage.clear();5. 获取键名 (Key)使用key(index)方法根据索引获取对应的键名。// 获取第一个键的名称不常用因为存储顺序不是开发人员控制的constfirstKeylocalStorage.key(0);6. 获取长度 (Length)使用length属性可以知道存储了多少个数据项。constnumberOfItemslocalStorage.length;实际示例场景记住用户的主题偏好// 1. 当用户选择主题时保存到 localStoragefunctionsaveTheme(themeName){localStorage.setItem(preferredTheme,themeName);applyTheme(themeName);// 立即应用主题}// 2. 页面加载时检查是否有保存的主题window.addEventListener(DOMContentLoaded,(){constsavedThemelocalStorage.getItem(preferredTheme);if(savedTheme){applyTheme(savedTheme);}else{applyTheme(light);// 默认主题}});// 3. 应用主题的函数functionapplyTheme(themeName){document.body.classNamethemeName;}场景在单页应用(SPA)中用 sessionStorage 存储临时表单数据// 用户在表单输入时实时保存到 sessionStorageformElement.addEventListener(input,(e){constformData{name:nameInput.value,email:emailInput.value};sessionStorage.setItem(draftFormData,JSON.stringify(formData));});// 页面加载时如果存在草稿则填充表单window.addEventListener(DOMContentLoaded,(){constdraftsessionStorage.getItem(draftFormData);if(draft){constformDataJSON.parse(draft);nameInput.valueformData.name;emailInput.valueformData.email;}});// 表单提交成功后清除草稿functiononFormSubmit(){// ... 提交逻辑sessionStorage.removeItem(draftFormData);// 清理临时数据}注意事项存储限制大小通常为5MB不同浏览器可能略有差异远大于Cookie的4KB。阻塞性localStorage和sessionStorage的操作是同步的意味着大量或复杂的操作可能会阻塞主线程影响页面性能。对于大量数据应考虑使用异步的 https://developer.mozilla.org/zh-CN/docs/Web/API/IndexedDB_API。非加密存储的数据不是加密的因此绝对不要用它存储密码、信用卡号等高度敏感的信息。错误处理在存储时可能会抛出错误例如用户关闭了存储权限或浏览器处于隐私模式。try{localStorage.setItem(key,value);}catch(e){console.error(Failed to save to storage:,e);// 在这里处理错误例如告知用户或使用其他存储方案}总结持久化作用域用途localStorage永久跨标签页长期偏好、需要持久化的数据sessionStorage一次会话单标签页临时状态、敏感操作、避免多标签干扰根据你需要的数据存活时间和可访问范围来选择使用哪一个。IndexedDB 是什么你可以把它理解成浏览器里自带的、本地的、小型数据库浏览器自己本地存数据不一定要联网适合做离线可用的 Web 应用前端离线数据存储大量数据缓存如电商商品列表本地草稿保存表单、草稿、本地记录如何使用IndexedDB核心思路打开 / 创建数据库指定版本版本变化时更新表结构创建对象仓库类似 MySQL 的表执行增删改查通过事务操作// 1. 初始化/打开数据库functionopenDB(dbName,version1){returnnewPromise((resolve,reject){// 浏览器兼容检测if(!window.indexedDB){reject(你的浏览器不支持 IndexedDB);return;}// 打开数据库不存在则创建constrequestindexedDB.open(dbName,version);// 数据库版本更新/首次创建时触发用于创建表/修改表结构request.onupgradeneeded(event){constdbevent.target.result;// 创建对象仓库表指定主键id自动递增if(!db.objectStoreNames.contains(users)){conststoredb.createObjectStore(users,{keyPath:id,autoIncrement:true});// 创建索引方便按name查询unique: false 允许重复store.createIndex(nameIndex,name,{unique:false});}console.log(数据库表初始化完成);};// 打开成功request.onsuccess(event){resolve(event.target.result);// 返回数据库实例};// 打开失败request.onerror(event){reject(打开数据库失败event.target.error);};});}// 2. 新增数据插入单条functionaddData(db,storeName,data){returnnewPromise((resolve,reject){// 开启事务指定表名 操作模式readwrite 读写readonly 只读consttransactiondb.transaction(storeName,readwrite);conststoretransaction.objectStore(storeName);constrequeststore.add(data);// 插入数据request.onsuccess(){resolve(数据新增成功);};request.onerror(event){reject(新增失败event.target.error);};});}// 3. 查询数据按主键id查functiongetDataById(db,storeName,id){returnnewPromise((resolve,reject){consttransactiondb.transaction(storeName,readonly);conststoretransaction.objectStore(storeName);constrequeststore.get(id);// 按主键查询request.onsuccess(event){resolve(event.target.result);// 返回查询结果};request.onerror(event){reject(查询失败event.target.error);};});}// 4. 修改数据按主键更新functionupdateData(db,storeName,data){returnnewPromise((resolve,reject){consttransactiondb.transaction(storeName,readwrite);conststoretransaction.objectStore(storeName);constrequeststore.put(data);// put有则更新无则新增request.onsuccess(){resolve(数据修改成功);};request.onerror(event){reject(修改失败event.target.error);};});}// 5. 删除数据按主键删functiondeleteData(db,storeName,id){returnnewPromise((resolve,reject){consttransactiondb.transaction(storeName,readwrite);conststoretransaction.objectStore(storeName);constrequeststore.delete(id);// 按主键删除request.onsuccess(){resolve(数据删除成功);};request.onerror(event){reject(删除失败event.target.error);};});}// 6. 关闭数据库functioncloseDB(db){db.close();console.log(数据库已关闭);}// 测试使用 asyncfunctiontestIndexedDB(){try{// 1. 打开数据库库名myDB版本1constdbawaitopenDB(myDB,1);// 2. 新增一条用户数据awaitaddData(db,users,{name:张三,age:20});awaitaddData(db,users,{name:李四,age:25});// 3. 查询id1的用户constuserawaitgetDataById(db,users,1);console.log(查询到id1的用户,user);// 输出{id:1, name:张三, age:20}// 4. 修改id1的用户年龄awaitupdateData(db,users,{id:1,name:张三,age:21});// 5. 删除id2的用户awaitdeleteData(db,users,2);// 6. 关闭数据库closeDB(db);}catch(error){console.error(操作失败,error);}}// 执行测试testIndexedDB();