Fork me on GitHub
秋染蒹葭

浏览器的数据存储方案之一:前端数据存储方案概览

HTML5+的离线本地存储有如下多种方案:
HTML5标准方案:cookie、localstorage、sessionstorage、websql、indexedDB
HTML5Plus扩展方案:plus.navigator.setCookie、plus.storage、plus.io

浏览器在提供了多种数据存储的技术,包括HTTP文件缓存、LocalStorage、 sessionStorage、cookie、indexDB、webSQL 、CatheStorage、Application Cache。对这几种方案需要熟悉。通常不同的网站,数据存储于不同的区域,并且一个网站只能访问自身的数据,BTW,数据访问不能跨域,不同的网站不能使用相同的数据库

localStorage方式

localStorage存储的数据没有时间限制,不会失效;在当前域下都可以直接获取

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//添加或修改
window.localStorage.setItem("name","zhyjor")
//获取
alert(window.localStorage.getItem("name"));
//删除
window.localStorage.removeItem(name)
//清空
window.localStorage.clear();
//也可与通过数组和“.”操作符来添加和获取
window.localStorage.name;
window.localStorage["name"]
//使用key()获取键的集合
for(var i=0;i < window.localStorage.length;i++){
var key=window.localStorage.key(i);
console.log(key);
}

注意:

  • localStorage只支持string类型的存储。无论存储的是什么数据结构,取出的都是string,Json数据需要经过stringfy()转换。读取的时候需要解析parse()
  • 官方推荐的是getItem\setItem这两种方法对其进行存取
  • localStorage拓展了cookie的4K限制,相当于一个5M大小的针对于前端页面的数据库。
  • localStorage不能被爬虫抓取到
  • IE8以上的IE版本才支持localStorage这个属性
  • 不同浏览器无法共享localStorage或sessionStorage中的信息。相同浏览器的不同页面间可以共享相同的localStorage(页面属于相同域名和端口)

兼容性

sessionStorage 方法

localStorage与sessionStorage的唯一一点区别就是localStorage属于永久性存储,而sessionStorage属于当会话结束的时候,sessionStorage中的键值对会被清空。

sessionStorage 方法针对一个 session 进行数据存储。当用户关闭浏览器窗口后,数据会被删除。

两者的方法相同!

storage事件

当储存的数据发生变化时,会触发storage事件。我们可以指定这个事件的回调函数。


window.addEventListener("storage",function onStorageChange(event) {  
     console.log(event.key);      
});  

event一个有四个属性

  • key:发生变化的键名
  • oldValue:更新前的值。如果该键为新增加,则这个属性为null
  • newValue:更新后的值。如果该键被删除,则这个属性为null。
  • url:原始触发storage事件的那个网页的网址。

监听storage变更事件会发现,当数据发生变化时本页是监听不到storage事件变更消息的。而同域的其他打开的页面反而监听到了该消息。该事件不在导致数据变化的当前页面触发。一个页面改变sessionStorage或localStorage的数据时,同域的其他打开的页面的storage事件会被触发,而原始页面并不触发storage事件。可以通过这种机制,实现多个窗口之间的通信。IE浏览器除外,它会在所有页面触发storage事件。

storage事件当前界面捕获

如何在当前页响应这些修改数据库的事件呢?

当前页面获取storage这个是有必要的,尤其是在单页面(SPA应用)开发时,这种限制几乎是致命的。单页面应用只在一个页面中渲染不同的内容,因此我们需要重写localStorage的方法来达到可以监听自己本身页面修改的效果。

此时我们需要重写localStorage的方法,并设置自定义的事件

1
2
3
4
5
6
7
8
9
10
11
var orignalSetItem = localStorage.setItem;
localStorage.setItem = function(key,newValue){
var setItemEvent = new Event("setItemEvent");
setItemEvent.newValue = newValue;
window.dispatchEvent(setItemEvent);
orignalSetItem.apply(this,arguments);
}
window.addEventListener("setItemEvent", function (e) {
alert(e.newValue);
});
localStorage.setItem("nm","1234");

Cookies方式

cookie数据始终在同源的http请求中携带,cookie在浏览器和服务器之间进行传递,cookie的数据还有path的概念,可以限制cookies只属于某个路径下,cookie数据不能超过4k,同时因为每次http请求都会携cookie,所以cookie只适合保存很小的数据,如会话标识。

比较三者的不同

cookie,localStorage,sessionStorage都可以实现客户端存储,三者的区别有哪些了?

从出现目的看

  • cookie作为最早期的被设计web浏览器存储少量数据,从底层看,它是作为http协议的一种扩展实现。cookie数据会自动在web浏览器和web服务器之间传输数据。
  • localStorage, sessionStorage是HTML5中新增的web存储的功能,它解决了客户端存储的一些缺点,并提供更强大的功能和操作API。

从有效时间看

  • cookie有效期:cookie默认有效期非常短暂,存在于web浏览器会话期间,当浏览器关闭,cookie也就消失了。如果要延长cookie的有效期,可以设置max-age属性(单位秒)
  • localStorage有效期:永不失效,除非web应用主动删除。
  • sessionStorage有效期:sessionStorage的有效期是和存储数据脚本所在的最顶层的窗口或者是浏览器标签是一样的,一旦窗口或者标签页被永久关闭了,存储的数据也就失效了。

从作用域看

  • cookie作用域:cookie作用域是通过domain文档源和path文档路径来确定的。默认情况下,cookie和创建它的web页面有关,并对web页面和该web页面同目录或者子目录的其他web页面可见。当设置path=”/“,它的作用域就变成文档源级别的了。
  • localStorage作用域:localStorage的作用域是限定在文档源级别的。文档源通过协议、主机名以及端口三者来确定。
  • sessionStorage作用域:sessionStorage的作用域也是限定在文档源级别。但需要注意的是,如果相同文档源的页面渲染在不同的标签中,sessionStorage的数据是无法共享的。

除了上述列举的,cookie和localStorage、sessionStorage在存储大小的限制也不一样, 由于每个浏览器的实现标准都不一样,只说一下RFC 2965推荐标准(浏览器保存cookie不超过300个,为每个服务器保存的cookie不超过20个,每个cookie大小不超过4KB)。localStorage、sessionStorage设置值时可以达到8M。Web Storage拥有setItem,getItem,removeItem,clear等方法,不像cookie需要前端开发者自己封装setCookie,getCookie。

document.cookie可以读取到cookie, 但是读取不到带有HTTPOnly 的参数的cookie,只能传输给服务器读写,这样就防止了前端的篡改,比如说:

document.cookie 的操作比webStorage麻烦的多,它是由等号和分号分隔开的字符串;

HTTP文件缓存

对于浏览器缓存参见《http协议详解之一:缓存》

webSQL

兼容性

浏览器对 Web SQL 数据库的兼容表——引自Can I Use

使用方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
window.onload = function () {
//var db = window.openDatabase("Web Sql DB");
//判断浏览器是否支持
if (window.openDatabase) {
//alert("浏览器支持");
//创建数据库
var db = window.openDatabase("Web_Sql_DB", "1.0", "Web SQL DB 测试", 20000);
if (db) {
//alert("数据库创建成功!");
//创建表
db.transaction(function (tx) {
tx.executeSql("Create Table tb1(id int,title Text)");
});
//插入数据
db.transaction(function (tin) {
tin.executeSql("insert into tb1(id,title) values(?,?)", [2, "WEB SQL"]);
})
db.transaction(function (tin) {
tin.executeSql("insert into tb1(id,title) values(?,?)", [3, "JQuery"]);
})
//删除
//db.transaction(function (tin) {
// tin.executeSql("delete from tb1 where title='WEB SQL'");
//})
//查询
db.transaction(function (tx) {
tx.executeSql("select * from tb1", [], function (x1, x2) {
for (var i = 0; i < x2.rows.length; i++) {
document.write("<b>" + x2.rows.item(i)['title'] + "</b><br/>")
}
}, function (x3) {
});
})
}
}
else {
alert("浏览器 不 支持!!!");
}
}

indexDB

IndexedDB 使用同源原则,所以它不能被任何其他源访问。进行大数据的存储,IndexedDB的储存空间比localStorage大得多,一般来说不少于250MB。IE的储存上限是250MB,Chrome和Opera是剩余空间的某个百分比.

是一种轻量级NOSQL数据库;一个网站可能有一个或多个 IndexedDB 数据库,每个数据库必须具有惟一的名称。一个数据库可包含一个或多个对象存储。一个对象存储(由一个名称惟一标识)是一个记录集合。每个记录有一个键 和一个值。该值是一个对象,可拥有一个或多个属性。键可能基于某个键生成器,从一个键路径衍生出来,或者是显式设置。一个键生成器自动生成惟一的连续正整数。键路径定义了键值的路径。

兼容性

使用indexedDB之前,最好使用以下代码,兼容不同浏览器

1
2
3
4
5
6
7
8
//数据库对象
window.indexedDB =window.indexedDB||window.webikitIndexedDB||window.mozIndexedDB||window.msIndexedDB;
//数据库事务
window.IDBTransaction = window.IDBTransaction||window.webikitIDBTransaction||window.mozIDBTransaction||window.msIDBTransaction;
//数据库查询条件
window.IDBKeyRange = window.IDBKeyRange||window.webkitIDBKeyRange||window.mozIDBKeyRange||window.msIDBKeyRange;
//游标
window.IBDCursor = window.IBDCursor ||window.webkitIBDCursor ||window.mozIBDCursor ||window.msIBDCursor ;

使用方法

1
2
3
4
5
6
7
var request = indexedDB.open('dbName', 1); // 打开 dbName 数据库
request.onerror = function(e){ // 监听连接数据库失败时执行
console.log('连接数据库失败');
}
request.onsuccess = function(e){ // 监听连接数据库成功时执行
console.log('连接数据库成功');
}

对比websql

WebSQL也是一种在浏览器里存储数据的技术,跟IndexedDB不同的是,IndexedDB更像是一个NoSQL数据库,而WebSQL更像是关系型数据库,使用SQL查询数据。

HTML5 indexedDB和Web SQL Database都是本地数据库数据存储,Web SQL Database数据库要出来的更早,然并卵。从2010年11月18日W3C宣布舍弃Web SQL database草案开始,就已经注定Web SQL Database数据库是明日黄花。

使用场景

在 IndexDB 中,我们可以创建多个数据库,一个数据库中创建多张表,一张表中存储多条数据——这足以 hold 住复杂的结构性数据。IndexDB 可以看做是 LocalStorage 的一个升级,当数据的复杂度和规模上升到了 LocalStorage 无法解决的程度,我们毫无疑问可以请出 IndexDB 来帮忙。

HTML5plus Runtime

HTML5plus Runtime,简称5+ Runtime,是运行于手机端的强化web引擎,除了支持标准HTML5外,还支持更多扩展的js api.业内之前有phonegap/Cordova方案,但是他们自带js api太少了,扩展api需要用原生语言开发,更致命的是这类方案的性能不足。封装成跨平台的HTML5plus规范,并将规范公开于www.HTML5plus.org,不做厂商私有API。包括二维码、摇一摇、语音输入、地图、支付、分享、文件系统、通讯录等常用API,可以方便简单的编写,并且可跨平台。如这些接口:plus.navigator.setCookie、plus.storage、plus.io,都可以用来存储。

mui是基于HTML5+ 的一套app前端UI框架。

Application Cache(离线缓存)

上述的内容主要涉及的是数据的存储,接下来的两种主要就是用于离线应用的开发了。

说得HTML5离线开发,我们通常第一反应是使用html5 manifest缓存技术,此技术已经出现很多年了。通过配置manifest 文件选择性的在本地存储,

使用方法

当浏览器第二次打开页面的时候,会优先从 applictionCache 来加载,然后检查 app.manifest 是否更新,如果有更新则拉取更新文件并且更新app.manifest;

1
2
3
4
5
6
7
8
9
10
11
<!DOCTYPE html>
<html lang="en" manifest="app.manifest">
<head>
<meta charset="UTF-8">
<title>Document</title>
<link rel="stylesheet" href="test.css">
</head>
<body>
<script src = 'test.js'></script>
</body>
</html>

Manifest 文件:

manifest 文件是简单的文本文件,它告知浏览器被缓存的内容(以及不缓存的内容)。manifest 文件可分为三个部分:

  • CACHE MANIFEST - 在此标题下列出的文件将在首次下载后进行缓存
  • NETWORK - 在此标题下列出的文件需要与服务器的连接,且不会被缓存
  • FALLBACK - 在此标题下列出的文件规定当页面无法访问时的回退页面(比如 404 页面)
1
2
3
4
5
6
7
8
9
10
11
12
#app.manifest
CACHE MANIFEST
# 2016-07-24 v1.0.0
/theme.css
/main.js
NETWORK:
login.jsp
FALLBACK:
/html/ /offline.html

Application Cache 被标准弃用,浏览器不兼容, 不成熟, 被serviceWorkers(是事件驱动的 worker,生命周期与页面无关,关联页面未关闭时,它也可以退出,没有关联页面时,它也可以启动) 替代

离线缓存与传统浏览器缓存区别

  • 离线缓存是针对整个应用,浏览器缓存是单个文件
  • 离线缓存断网了还是可以打开页面,浏览器缓存不行
  • 离线缓存可以主动通知浏览器更新资源

cacheStorage

用来替代Application cache的解决方案;通过window.caches 可以获取到Caches 对象,api 是下面的:

1
2
3
4
5
window.caches.open() // 打开一个caches对象并且返回promise 对象;
window.caches.has( ) //检查如果包含一个caches对象,则返回promise对象;
window.caches.delete()
window.caches.key()
window.caches.metch()

cacheStorage 是基于serviceWorker, serviceWorker是在后台独立线程运行的js脚本,通过 message/ postmessage 方法与页面进行通信;

但是短期内兼容性还是很差的;

flash缓存

这种方式基本不用,这一方法主要基于flash有读写浏览器端本地目录的功能,同时也可以向js提供调用的api,则页面可以通过js调用flash去读写特定的磁盘目录,达到本地数据缓存的目的。

总结

Web Storage / Web SQL Database / Indexed Database 的数据都存储在浏览器对应的用户配置文件目录(user profile directory)下,以 Windows 7 为例,Chrome 的数据存储在”C:\Users\your-account-name\AppData\Local\Google\Chrome\User Data\Default\”下,而 Firefox 的数据存储在”C:\Users\your-account-name\AppData\Local\Mozilla\Firefox\Profiles\”目录下。

cookie文件存储于documents and settings\userName\cookie\文件夹下。通常的命名格式为:userName@domain.txt。

较多的缓存机制目前主流浏览器并不兼容,不过可以使用polyfill的方法来处理

参考资料
5分钟带你学习浏览器8大数据存储技术
前端HTML5几种存储方式的总结
深入了解 Service Worker ,看这篇就够了
借助Service Worker和cacheStorage缓存及离线开发
9大浏览器端缓存机制分析
HTML5 进阶系列:indexedDB 数据库
IndexedDB使用与出坑指南
HTML5 indexedDB 前端本地存储数据库实例教程
新一代的前端存储方案–indexedDB
很全很全的前端本地存储讲解

本文标题:浏览器的数据存储方案之一:前端数据存储方案概览

文章作者:zhyjor

发布时间:2018年04月11日 - 10:04

最后更新:2023年10月11日 - 02:10

原始链接:https://zhyjor.github.io/2018/04/11/浏览器的数据存储方案之一:前端数据存储方案概览/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

🐶 您的支持将鼓励我继续创作 🐶

热评文章