现在前后端分离是比较流行的开发方案,在 SPA 的开发过程中难免需要存储一些数据到浏览器,比如认证判断的 Token
。现代常用浏览器的本地持久存储方案基本分为Cookie
、 LocalStorage(sessionStorage)
和IndexedDB
。本文就不讨论 Cookie
了。
一、LocalStorage(sessionStorage)
的概念
LocalStorage 是 HTML5加入的一个新特性,从命名就知道其目的是作为本地存储来使用,解决了 Cookie
存储空间不足的问题,一般 LocalStorage
在浏览器的存储空间是5MB
,而 Cookie
中每条 cookie
大约是4KB
。SessionStorage
与 LocalStorage
唯一的区别是:SessionStorage
在会话结束时就会被 清空数据,而LocalStorage
可以持久存储。
LocalStorage
的优劣
1、LocalStorage
存储空间明显提升,可以存储较多的数据;
2、LocalStorage
可以长久存储数据,只要存储一次就可以长久保留在本地,除非主动清空数据;
3、LocalStorage
是 HTML5
的新特性,只会被现代浏览器支持,IE8以下的IE浏览器就不支持该特性;
4、LocalStorage
只能存储字符串
5、在隐私模式下,不能使用 LocalStorage
;
6、LocalStorage
不会被爬虫嗅探并抓取;
7、LocalStorage
的使用是遵循同源策略。
LocalStorage
的使用方法
1、在使用 LocalStorage
之前需要检测当前浏览器是否支持。
1 | if(!window.localStorage){ |
2、LocalStorage
的数据写入可以有3种方式,其实都是键值对操作:
1 | if(!window.localStorage){ |
一般使用 storage.setItem
这种方式比较好。
3、LocalStorage
的数据读取
1 | if(!window.localStorage){ |
一般使用 storage.getItem
这种方式比较好。
4、LocalStorage
的其他数据操作
删除某个键值:window.localStorage.removeItem('key')
清空当前网站的LocalStorage
:window.localStorage.clear()
一般使用 LocalStorage
来存储简单的数据(字符串)就可以满足了,但在日益复杂的应用开发中,难免需要存储复杂的结构化数据,而且有可能存储的数据超过5MB
,这时我们就需要考虑使用 IndexedDB
了
二、IndexedDB
的概念
1、IndexedDB
顾名思义是一种内置在浏览器中数据库,而且是一种非关系型的数据库,即不需要编写SQL
语句去操作数据库,而且存储的数据格式是JSON
。
2、IndexedDB
不像我们平时服务器上使用的 NoSQL 数据库,IndexedDB
没有表的概念,在IndexedDB
中是叫object store
,其实平时就可以把object store
看做数据表。
3、IndexedDB
的每次操作都是一个事务,每一个对数据库操作是在一个事务的上下文中执行的。
4、IndexedDB
的每次数据库操作都需要先打款object store
,再执行指定的操作,不能一直打开某个object store
。
5、IndexedDB
的所有操作都是异步的。
三、IndexedDB
在 React
中的实践
因为我目前主要专注React
项目的开发,而且IndexedDB
的原生 api 有点奇怪,在我的项目中我是使用 Dexie这个基于IndexedDB
api 封装的操作库。后面就阐述一下如何使用Dexie
进行IndexedDB
的数据操作。
1、安装npm i -S dexie
2、在项目根目录建立一个db
文件夹,新建一个文件db.js
,在db.js
中定义数据库;
1 |
|
IndexedDB
使用 version
来区分不同版本号,因为不同的版本可能使用不同的 store
结构,每次更改 store
的结构,需要增加 version
的值,而且旧的版本需要保留。
3、数据操作
在db
目录中新建operations.js
文件,定义一些常用的数据操作方法
1 | import db from 'db/db'; |
若要增加其他特殊的数据操作,就直接在operations.js
文件中增加方法即可,避免重复的编码。
IndexedDB
理论上的存储空间是电脑硬盘容量的一般,所以存储空间超级充足了。
四、解决IndexedDB
的异步问题
前文有提到IndexedDB
的所有数据操作都是异步的,在一些情况下我们需要模拟同步操作,例如把菜单的配置放在IndexedDB
中,那么每次从IndexedDB
获取到菜单定义数据后需要回调数据显示,有点麻烦。我在项目中使用mobx
状态管理器来同步所有的IndexedDB
数据,只有不刷新页面,就可以同步操作IndexedDB
数据了。目前都是读取操作,数据都是从服务器配置好的,存储在IndexedDB
是不需要每次从服务器获取。
一般在更新IndexedDB
中数据的时候,就更新mobx
中的 store数据。
五、总结
浏览器的本次存储在现在 web 应用开发中还是比较重要的,掌握了这些前端本地存储方法有利于提升应用以及应用共享数据。