最近在项目中使用了部分的前端存储,之前只有一些简单的了解,今天就趁这个机会把前端存储进行深入研究一番。
写在开始
前端存储的好处:
- 方便网页的加载,避免了在发送请求收到响应前页面的空白期。
- 也可以在非强制性要求实时最新数据时减少向服务端的请求,加快渲染速度。
- 在网络不佳或无网络时仍有离线数据可以查看。
前端存储的方式:
首先我们应该先清除大概都有哪些存储方式,对此我们只需要打开控制台,选择 application 来进行查看。
我们可以看到,存储大概分为两大类,一类为 存储类 ,另一类为 缓存类。
存储类:
- Web存储 (Web Storage):HTML 5 中提出的存储方式,容量有 5 M。
- localStorage
- sessionStorage
- Cookie:浏览器普遍支持的基于 HTTP 协议的存储方式,但容量只有 4 KB
- 数据库存储:
- IndexDB
- Web SQL
缓存类:
- Cache Storage: 在 Service Worker 的规范中提出,一般配合 Service Worker 进行离线缓存。
- Application Cache: 在 HTML5.1提出的缓存方式,可用来构建离线应用。
介绍
个子小的长兄 —— Cookie
HTTP Cookie,它最初适用于客户端存储会话信息的、这个标准要求服务器对 HTTP 请求设置 Set-Cookie HTTP 头作为响应的一部分,其中会包含有会话信息。浏览器在 Cookie 中存储绘画信息,并在发送请求时将 Cookie 一起发送过去。
Cookie 的构成
我们先打开 github 之后进入控制台查看一下
- 名称
- 值
- 域
- 路径
- 失效时间 (格林威治时间)
- 大小
- 是否为 HTTP请求
- 安全性
域 路径 失效时间 和 安全性 都是服务器给浏览器的指示,他们不会随着请求发送给服务器,发送给服务器的只有名称与值对。
Cookie 的限制性
- 如果设定了 Cookie 的过期时间,那么 Cookie 会在到期时自动失效。
- 如果没有设定过期时间,那么 Cookie 就是 session 级别的,即浏览器关闭时 Cookie 自动消失。
Cookie 的优缺点
优点:
1. 可以控制过期时间,不会永久有效,有一定的安全保障。
2. 可进行扩展,可跨域共享。
3. 通过加密与安全传输技术 (SSL) ,可以减少 Cookie 被破解的可能性。
4. 有较高的兼容性。
复制代码
缺点:
1. 有一定的数量与长度限制,每个 Cookie 长度不能超过 4 KB ,否则超出部分会被截掉。
2. 请求头上的数据容易被拦截攻击。
复制代码
新生力量 Web Storage
LocalStorage 与 SessionStorage
我们可以先看一下它的兼容性,许多浏览器已经完全支持了它:
数据来源: MDN
出现原因
- 克服 Cookie 的一些限制,同时存储一些需要严格控制在客户端,不需要发送给服务器的一些数据。
- 提供了除 Cookie 之外的另一种存储会话的途径。
- 提供了一种大容量存储空间来跨回话存储数据的途径。
如何查看
它们都是直接作为 window
对象的属性存在的,我们可以直接通过 window.localStorage
与 window.sessionStorage
来访问。
同时,我们观察到 Web Storage 只能储存字符串,如果用 Web Storage 存储对象,会出现
[Object Object]
, 可以用JSON.stringify
与JSON.parse
方法来解决这个问题。
Web Storage 实例方法
- clear:删除所有值
- getItem(name): 根据传入的键来获取对应的值。
- key(index): 获得所对应索引的键,名称。
- removeItem(name): 删除键对应的键值对
- setItem(name, value): 为指定的 name 设置一个对应的值。
没有感情的 sessionStorage
- 同源策略: 不同于 Cookie, sessionStorage 访问限制更高,只有当前设定了 sessionStorage 的域下才能访问。
- 单标签页: 两个相同域下的标签页不能互通。
- 在关闭标签页或者新开的标签页下都不能访问之前写下的 sessionStorage
- 刷新标签页依然可以访问 sessionStorage
使用的场景:
1. 主要针对会话级的小数据的存储。
2. 存储一些在当前页面刷新仍然需要存储,但是关闭后不需要留下的信息。
3. 很适合单页应用的使用,可以用来存储登录态信息等。
复制代码
不离不弃的 localStorage
- 同源策略:和 sessionStorage 一样,要访问同一个 localStorage 页面必须来自同一个域名,同种协议,同种端口。
- localStorage 设定后,刷新或者重新打开标签页,关闭浏览器重新打开原来的标签页也可以访问到。
使用的场景:
1. 持久性的保存客户端数据,只能通过 JavaScript 删除或者用户清除浏览器缓存。
2. 如果有一些稍大量的数据,例如编辑器的自动保存等。
3. 多页面间访问共同数据。 sessionStorage 只能用于一个标签页,而localStorage可以在多个标签页之间共享。
复制代码
sessionStorage 与 localStorage 的区别
- 生命周期:localStorage 是本地存储,没有期限,只能用户自己操作来删除。 sessionStroage 是会话存储,页面关闭数据就会丢失。
- sessionStorage 有单标签页的限制,localStorage则没有。
Storage 事件
我们对 Storage 对象进行任何的操作,都会在文档上触发 Storage 事件, 这个事件的 event 对象有以下属性:
- domain:发生变化的存储空间的域名。
- key:设置或删除的键名
- newValue: 如果是设置值,则是新值。如果是删除键,则为null。
- oldValue:键被更改之前的值。
数据库级别: IndexDB 与 Web SQL
Web SQL 类似关系型数据库, 它使用 sql 语句进行相关操作。
indexDB 类似 NoSQL , 直接使用 js 的方法操作数据。
特点:
- 访问:indexDB 和 Web SQL 和 Web Storage 一样,均是只能在创建数据库的域名下才能访问。
- 存储时间:存储时间为永久,除非用户清除数据,他可用作长期的存储。
- 大小限制:二者其实没有强制限制。只是 indexDB 在数据超过 50 M 之后会从浏览器弹出一个框让你确认。
- 性能: indexDB 查询速度会相对较慢,而 Web SQL 的性能相对较快。
实际操作
第一步打开数据库
var request = indexedDB.open(name, version);
复制代码
第一个参数为数据库的名称,第二个参数为数据库的版本号。
第二步添加数据
创建事务,并加上数据读写权限。
var transaction = db.transaction(storeName, 'readwrite');
复制代码
获取 objectStore 再调用add方法添加数据
var store = transaction.objectStore(storeName);
var request = store.get(key);
request.onsuccess = function (e) {
data = e.target.result;
console.log(student.name);
};
复制代码
第三步删除数据
删除也需要创建事务,调用删除接口 ,通过key删除对象。
var transaction = db.transaction(storeName, 'readwrite');
var store = transaction.objectStore(storeName);
store.delete(key);
复制代码
第四步查找数据
- 按key查找
开启事务,获取到 objectStore ,调用get()方法获取对象。
var transaction = db.transaction(storeName, 'readwrite');
var store = transaction.objectStore(storeName);
var request = store.get(key);
request.onsuccess = function (e) {
data = e.target.result;
console.log(student.name)
};
复制代码
- 使用索引查找
我们在使用索引之前需要先创建索引,它使用createIndex
方法创建索引,方法有三个参数: 索引名称、索引属性字段名,索引属性值是否唯一。
objectStore.createIndex('name','name', {
unique: false
})
复制代码
创建好了索引,我们就可以使用索引进行查询:
var transaction = db.transaction(storeName);
var store = transaction.objectStore(storeName);
var index = store.index(search_index);
index.get(value).onsuccess = function (e) {
data = e.target.result;
console.log(student.id);
}
复制代码
- 游标遍历数据
var transaction = db.transaction(storeName);
var store = transaction.objectStore(storeName);
var request = store.openCursor(); //成功打开游标
var dataList = new Array();
var i = 0;
request.onsuccess = function (e) {
var cursor = e.target.result;
if (cursor) {
console.log(cursor.key);
dataList[i] = cursor.value;
console.log(dataList[i].name);
i++;
cursor.continue();
}
data = dataList;
}
复制代码
第五步,更新对象
为了更新对象,我们首先要把它取出来,进行修改之后再放回去。
var transaction = db.transaction(storeName, 'readwrite');
var store = transaction.objectStore(storeName);
var request = store.get(key);
request.onsuccess = function (e) {
var data = e.target.result;
for (a in newData) {
data.a = newData.a;
}
store.put(data);
}
复制代码
第六步,关闭与删除
关闭数据库需要调用数据库的 close 方法
db.close();
复制代码
删除数据库使用数据库对象 deleteDatabase 方法
function deleteDB (name) {
indexedDB.deleteDatabase(name);
}
复制代码
IndexDB 特点
- 它的数据保存在对象存储空间中。
- 创建对象存储空间,首先先定义一个键,之后添加数据。
- 可以使用游标查询。
indexDB 的兼容性还是一大问题,Web SQL 虽然过时,但兼容性却仍然非常好,移动端几乎均可用。
Cache Storage
Cache Storage
是用来存储 Response
对象 ,也就是对 HTTP 响应进行缓存。 Cache Storage
是多个 cache
的集合,每个 cache
可以存储多个响应对象。它基于 Promise。这里不做详细的赘述。
Application Cache
它是 HTML5 中新引入的应用程序换粗技术,它的出现意味着 web 应用可以通过缓存,在没有网络的环境下运行,构建离线应用。
优点:
- 离线浏览
- 提升页面的载入速度
- 降低服务器的压力
一般来说 Application Cache
只用来存储一些静态资源,它的使用方式主要需要两个步骤:
1.服务端维护一个 manifest
清单
2.浏览器端进行一个设置。
<html manifest="demo">
复制代码
一般的,我们必须给 manifest 文件设置正确的 MIME-type 为 "text/cache-manifest",它需要在服务器端进行配置。
在 Progressive Web Application 中, Application Cache 配合 Service Worker 承担着主要的任务。
参考文献
MDN: LocalStorage , sessionStorage, indexDB
本地存储与离线存储
前端存储之IndexDB