浏览器储存之Cookie、sessionStorage、localStorage和indexedDB区别与详解
一般在项目中我们逗需要把信息存储在本地的情况,比如权限验证的token、用户信息、埋点计数、客户配置的皮肤信息或语言种类等,我们可以暂存一下避免浏览器不必要的请求和客户多余操作,较少请求从而提高性能以给客户使用带来方便。
那么浏览器存储有哪些方法呢,主要有cookie、localStorage、sessionStorage
cookie属于文档对象模型DOM树根节点document,而 sessionStorage 和 localStorage 属于浏览器对象模型BOM的对象window
其中 sessionStorage 和 localStorage 是 HTML5 Web Storage API 提供的
- sessionStorage:为每一个给定的源(given origin)维持一个独立的存储区域,该存储区域在页面会话期间可用(即只要浏览器处于打开状态,包括页面重新加载和恢复)
- localStorage:同样的功能,但是在浏览器关闭,然后重新打开后数据仍然存在。
一、Cookie -会话跟踪技术
1、cookie的存取
document.cookie = "username=zhangsan";
document.cookie = "username=zhangsan; expires=Thu, 18 Dec 2013 12:00:00 GMT; path=/"
console.log(document.cookie);
- path
路径,值可以是一个目录,或者是一个路径。
如果cc.com/test/index.html 建立了一个cookie,那么在cc.com/test/目录里的所有页面,以及该目录下面任何子目录里的页面都可以访问这个cookie。因此在cc.com/test/test2/test3 里的任何页面都可以访问cc.com/test/index.html建立的cookie。若cc.com/test/ 若想访问cc.com/test/index.html设置的cookes,需要把cookies的path属性设置成“/”。
在指定路径的时候,凡是来自同一服务器,URL里有相同路径的所有WEB页面都可以共享cookies。
- domain
主机名,是指同一个域下的不同主机,例如:www.baidu.com和map.baidu.com就是两个不同的主机名。默认情况下,一个主机中创建的cookie在另一个主机下是不能被访问的,但可以通过domain参数来实现对其的控制:document.cookie = “name=value;domain=.baidu.com”
这样,所有*.baidu.com的主机都可以访问该cookie。
- expires
过期时间,当过了到期日期时,浏览器会自动删除该cookie,如果想删除一个cookie,只需要把它过期时间设置成过去的时间即可
比如希望设置过期时间一年:new Date().getTime() + 365 * 24 * 60 * 60 * 1000
如果不设置过期时间,则表示这个cookie生命周期为浏览器会话期间,只要关闭浏览器窗口,cookie就消失了
2、特点
- 只能使用文本 (如果浏览器可以随意在客户端机器上生成文件,比如身份牌是个定时炸弹,安全问题将会变得非常严重)
- 单条存储有大小限制 4KB (文件若没有大小限制,比如身份牌的重量是140斤,挂脖子能不能累死?)
- 数量限制 一般浏览器,限制大概在50条左右,你家的门禁卡里能存的下一部蓝光高清么?
- 读取有域名限制 不可跨域读取,只能由来自 写入cookie的 同一域名 的网页可进行读取简单的讲就是,谁写的cookie,谁才有权利读取。
(身份牌是我发你的,当然只有我能读取,你媳妇儿的手机自动连接了邻居老王家的wifi,你知道这意味着什么吗?) - 时效限制 每个cookie都有时效,最短的有效期是,会话级别:就是当浏览器关闭,那么cookie立即销毁 。(安全学基本理论:密码锁每次打开都需要重新输入密码,输入一次密码,以后就不再验证,就没有安全可言 )
3.优缺点
1.IE6或更低版本最多20个cookie
2.IE7和之后的版本最后可以有50个cookie。
3.Firefox最多50个cookie
4.chrome和Safari没有做硬性限制
Opera 会清理近期最少使用的Firefox会随机清理 4096字节,为了兼容性,一般不能超过 IE 提供了一种存储可以持久化用户数据,叫做IE5.0就开始支持。每个数据最多128K,每个域名下最多1M。这个持久化数据放在缓存中,如果缓存没有清理,那么会一直存在。
优点:极高的扩展性和可用性
1.通过良好的编程,控制保存在cookie中的session对象的大小。
2.通过加密和安全传输技术(SSL),减少cookie被破解的可能性。
3.只在cookie中存放不敏感数据,即使被盗也不会有重大损失。
4.控制cookie的生命期,使之不会永远有效。偷盗者很可能拿到一个过期的cookie。
缺点:
1.Cookie
数量和长度的限制。每个domain最多只能有20条cookie,每个cookie长度不能超过4KB,否则会被截掉。
2.安全性问题。如果cookie被人拦截了,那人就可以取得所有的session信息。即使加密也与事无补,因为拦截者并不需要知道cookie的意义,他只要原样转发cookie就可以达到目的了。
3.有些状态不可能保存在客户端。例如,为了防止重复提交表单,我们需要在服务器端保存一个计数器。如果我们把这个计数器保存在客户端,那么它起不到任何作用。
4、插件
Vue
名称:js-Cookie
npm: npm install js-cookie --save
地址:https://www.npmjs.com/package/js-cookie
React
名称:react-cookies
npm:npm install react-cookies --save
地址: https://www.npmjs.com/package/react-cookies
二、localStorage
以键值对(Key-Value)的方式存储,永久存储,永不失效,除非手动删除。IE8+支持,每个域名限制5M。
1、存取
window.localStorage.username = 'hehe' // 设置
window.localStorage.setItem('username', 'hehe') // 设置
window.localStorage.getItem('username') // 读取
window.localStorage.removeItem('username') // 删除
window.localStorage.key(1) // 读取索引为1的值
window.localStorage.clear() // 清除所有
2、localStorage 的优势
1、localStorage 拓展了 cookie 的 4K 限制。
2、localStorage 会可以将第一次请求的数据直接存储到本地,这个相当于一个 5M 大小的针对于前端页面的数据库,相比于 cookie 可以节约带宽,但是这个却是只有在高版本的浏览器中才支持的。
3、localStorage 的局限
1、浏览器的大小不统一,并且在 IE8 以上的 IE 版本才支持 localStorage 这个属性。
2、目前所有的浏览器中都会把localStorage的值类型限定为string类型,这个在对我们日常比较常见的JSON对象类型需要一些转换。
3、localStorage在浏览器的隐私模式下面是不可读取的。
4、localStorage本质上是对字符串的读取,如果存储内容多的话会消耗内存空间,会导致页面变卡。
5、localStorage不能被爬虫抓取到。
localStorage 与 sessionStorage 的唯一一点区别就是 localStorage 属于永久性存储,而 sessionStorage 属于当会话结束的时候,sessionStorage 中的键值对会被清空。
4、localStorage 使用前
首先在使用 localStorage 的时候,我们需要判断浏览器是否支持 localStorage 这个属性:
if(! window.localStorage){alert("浏览器不支持localstorage");return false;
}else{//主逻辑业务
}
写法
if(!window.localStorage){alert("浏览器不支持localstorage");return false;
}else{var storage=window.localStorage;//写入a字段storage["a"]=1;//写入b字段storage.b=1;//写入c字段storage.setItem("c",3);console.log(typeof storage["a"]);console.log(typeof storage["b"]);console.log(typeof storage["c"]);
}
5、localStorage 键的获取
使用 key() 方法,向其中出入索引即可获取对应的键。
var storage = window.localStorage;
storage.a = 1;
storage.setItem("c",3);for (var i=0;i<storage.length;i++) {var key = storage.key(i);console.log(key);
}
6、localStorage 其他注意事项
一般我们会将 JSON 存入 localStorage 中,但是在 localStorage 会自动将 localStorage 转换成为字符串形式。
这个时候我们可以使用 JSON.stringify()
这个方法,来将 JSON 转换成为 JSON 字符串。
if (!window.localStorage) {alert("浏览器不支持localstorage");
} else {var storage = window.localStorage;var data = {name:'xiecanyong',sex:'man',hobby:'program'};var d = JSON.stringify(data);storage.setItem("data",d);console.log(storage.data);
}
读取之后要将 JSON 字符串转换成为 JSON 对象,使用JSON.parse()
方法:
var storage = window.localStorage;
var data = {name:'xiecanyong',sex:'man',hobby:'program'
};
var d = JSON.stringify(data);
storage.setItem("data",d);//将JSON字符串转换成为JSON对象输出
var json = storage.getItem("data");
var jsonObj = JSON.parse(json);
// 打印出来是 Object 对象
console.log(typeof jsonObj);
三、sessionStorage
sessionStorage操作的方法与localStroage是一样的,区别在于 sessionStorage 在关闭页面后即被清空,而 localStorage 则会一直保存。很多时候数据只需要在用户浏览一组页面期间使用,关闭窗口后数据就可以丢弃了,这种情况使用sessionStorage就比较方便。
注意,刷新页面sessionStorage不会清除,但是打开同域新页面访问不到。
存取
window.sessionStorage.username = 'hehe' // 设置
window.sessionStorage.setItem('username', 'hehe') // 设置
window.sessionStorage.getItem('username') // 读取
window.sessionStorage.removeItem('username') // 删除
window.sessionStorage.key(1) // 读取索引为1的值
window.sessionStorage.clear() // 清除所有
四、web storage和cookie的区别
cookie相似,区别是它是为了更大容量存储设计的。Cookie都会被发送过去,这样无形中浪费了带宽,另外 除此之外,setItem
,getItem
,removeItem
,clear
等方法,不像setCookie
,getCookie
。
但是Cookie的作用是与服务器进行交互,作为Web Storage仅仅是为了在本地“存储”数据而生
浏览器的支持除了UserData其实就是web storage。
sessionStorage都具有相同的操作方法,例如removeItem
等。
五、IndexedDB
IndexedDB 就是浏览器提供的本地数据库,它可以被网页脚本创建和操作。IndexedDB 允许储存大量数据,提供查找接口,还能建立索引。这些都是 LocalStorage 所不具备的。就数据库类型而言,IndexedDB 不属于关系型数据库(不支持 SQL 查询语句),更接近 NoSQL 数据库。
1、特点
IndexedDB 具有以下特点。
键值对储存。 IndexedDB 内部采用对象仓库(object store)存放数据。所有类型的数据都可以直接存入,包括 JavaScript 对象。对象仓库中,数据以"键值对"的形式保存,每一个数据记录都有对应的主键,主键是独一无二的,不能有重复,否则会抛出一个错误。
异步。 IndexedDB 操作时不会锁死浏览器,用户依然可以进行其他操作,这与 LocalStorage 形成对比,后者的操作是同步的。异步设计是为了防止大量数据的读写,拖慢网页的表现。
支持事务。 IndexedDB 支持事务(transaction),这意味着一系列操作步骤之中,只要有一步失败,整个事务就都取消,数据库回滚到事务发生之前的状态,不存在只改写一部分数据的情况。
同源限制。 IndexedDB 受到同源限制,每一个数据库对应创建它的域名。网页只能访问自身域名下的数据库,而不能访问跨域的数据库。
储存空间大。 IndexedDB 的储存空间比 LocalStorage 大得多,一般来说不少于 250MB,甚至没有上限。
支持二进制储存。 IndexedDB 不仅可以储存字符串,还可以储存二进制数据(ArrayBuffer 对象和 Blob 对象)。
2、概念
IndexedDB 是一个比较复杂的 API,涉及不少概念。它把不同的实体,抽象成一个个对象接口。学习这个 API,就是学习它的各种对象接口。
- 数据库:IDBDatabase 对象
- 对象仓库:IDBObjectStore 对象
- 索引: IDBIndex 对象
- 事务: IDBTransaction 对象
- 操作请求:IDBRequest 对象
- 指针: IDBCursor 对象
- 主键集合:IDBKeyRange 对象
下面是一些主要的概念。
(1)数据库
数据库是一系列相关数据的容器。每个域名(严格的说,是协议 + 域名 + 端口)都可以新建任意多个数据库。
IndexedDB 数据库有版本的概念。同一个时刻,只能有一个版本的数据库存在。如果要修改数据库结构(新增或删除表、索引或者主键),只能通过升级数据库版本完成。
(2)对象仓库
每个数据库包含若干个对象仓库(object store)。它类似于关系型数据库的表格。
(3)数据记录
对象仓库保存的是数据记录。每条记录类似于关系型数据库的行,但是只有主键和数据体两部分。主键用来建立默认的索引,必须是不同的,否则会报错。主键可以是数据记录里面的一个属性,也可以指定为一个递增的整数编号。
{ id: 1, text: 'foo' }
上面的对象中,id属性可以当作主键。
数据体可以是任意数据类型,不限于对象。
(4)索引
为了加速数据的检索,可以在对象仓库里面,为不同的属性建立索引。
(5)事务
数据记录的读写和删改,都要通过事务完成。事务对象提供error、abort和complete三个事件,用来监听操作结果。
3、操作流程
IndexedDB 数据库的各种操作,一般是按照下面的流程进行的。这个部分只给出简单的代码示例,用于快速上手,详细的各个对象的 API 请看这里。
3.1 打开数据库
使用 IndexedDB 的第一步是打开数据库,使用indexedDB.open()
方法。
// indexedDB.open('name', 'version')
// 返回一个 IDBRequest 对象
var request = window.indexedDB.open(databaseName, version);
这个方法接受两个参数,第一个参数是字符串,表示数据库的名字。如果指定的数据库不存在,就会新建数据库。第二个参数是整数,表示数据库的版本。如果省略,打开已有数据库时,默认为当前版本;新建数据库时,默认为1。
indexedDB.open()
方法返回一个 IDBRequest 对象。这个对象通过三种事件error
、success
、upgradeneeded
,处理打开数据库的操作结果。
(1)error 事件
error事件表示打开数据库失败。
request.onerror = function (event) {console.log('数据库打开报错');
};
(2)success 事件
success事件表示成功打开数据库。
var db;request.onsuccess = function (event) {db = request.result;console.log('数据库打开成功');
};
这时,通过request对象的result属性拿到数据库对象。
(3)upgradeneeded 事件
如果指定的版本号,大于数据库的实际版本号,就会发生数据库升级事件upgradeneeded。
var db;request.onupgradeneeded = function (event) {db = event.target.result;
}
这时通过事件对象的target.result
属性,拿到数据库实例。
3.2 新建数据库
新建数据库与打开数据库是同一个操作。如果指定的数据库不存在,就会新建。不同之处在于,后续的操作主要在upgradeneeded
事件的监听函数里面完成,因为这时版本从无到有,所以会触发这个事件。
通常,新建数据库以后,第一件事是新建对象仓库(即新建表)。
request.onupgradeneeded = function(event) {db = event.target.result;var objectStore = db.createObjectStore('person', { keyPath: 'id' });
}
上面代码中,数据库新建成功以后,新增一张叫做person的表格,主键是id。
更好的写法是先判断一下,这张表格是否存在,如果不存在再新建。
request.onupgradeneeded = function (event) {db = event.target.result;var objectStore;if (!db.objectStoreNames.contains('person')) {objectStore = db.createObjectStore('person', { keyPath: 'id' });}
}
主键(key)是默认建立索引的属性。比如,数据记录是 { id: 1, name: ‘张三’ },那么 id 属性可以作为主键。主键也可以指定为下一层对象的属性,比如 { foo: { bar: ‘baz’ } } 的 foo.bar 也可以指定为主键。
如果数据记录里面没有合适作为主键的属性,那么可以让 IndexedDB 自动生成主键。
var objectStore = db.createObjectStore('person',{ autoIncrement: true }
);
上面代码中,指定主键为一个递增的整数。
新建对象仓库以后,下一步可以新建索引。
request.onupgradeneeded = function(event) {db = event.target.result;var objectStore = db.createObjectStore('person', { keyPath: 'id' });objectStore.createIndex('name', 'name', { unique: false });objectStore.createIndex('email', 'email', { unique: true });
}
上面代码中,IDBObject.createIndex()
的三个参数分别为索引名称、索引所在的属性、配置对象(说明该属性是否包含重复的值)。
3.3 新增数据
新增数据指的是向对象仓库写入数据记录。这需要通过事务完成。
function add() {var request = db.transaction(['person'], 'readwrite').objectStore('person').add({ id: 1, name: '张三', age: 24, email: 'zhangsan@example.com' });request.onsuccess = function (event) {console.log('数据写入成功');};request.onerror = function (event) {console.log('数据写入失败');}
}add();
上面代码中,写入数据需要新建一个事务。新建时必须指定表格名称和操作模式(“只读"或"读写”)。新建事务以后,通过IDBTransaction.objectStore(name)
方法,拿到 IDBObjectStore 对象,再通过表格对象的add()方法,向表格写入一条记录。
写入操作是一个异步操作,通过监听连接对象的success
事件和error
事件,了解是否写入成功。
3.4 读取数据
读取数据也是通过事务完成。
function read() {var transaction = db.transaction(['person']);var objectStore = transaction.objectStore('person');var request = objectStore.get(1);request.onerror = function(event) {console.log('事务失败');};request.onsuccess = function( event) {if (request.result) {console.log('Name: ' + request.result.name);console.log('Age: ' + request.result.age);console.log('Email: ' + request.result.email);} else {console.log('未获得数据记录');}};
}read();
上面代码中,objectStore.get()
方法用于读取数据,参数是主键的值。
3.5 遍历数据
遍历数据表格的所有记录,要使用指针对象 IDBCursor。
function readAll() {var objectStore = db.transaction('person').objectStore('person');objectStore.openCursor().onsuccess = function (event) {var cursor = event.target.result;if (cursor) {console.log('Id: ' + cursor.key);console.log('Name: ' + cursor.value.name);console.log('Age: ' + cursor.value.age);console.log('Email: ' + cursor.value.email);cursor.continue();} else {console.log('没有更多数据了!');}};
}readAll();
上面代码中,新建指针对象的openCursor()方法是一个异步操作,所以要监听success
事件。
3.6 更新数据
更新数据要使用IDBObject.put()
方法。
function update() {var request = db.transaction(['person'], 'readwrite').objectStore('person').put({ id: 1, name: '李四', age: 35, email: 'lisi@example.com' });request.onsuccess = function (event) {console.log('数据更新成功');};request.onerror = function (event) {console.log('数据更新失败');}
}update();
上面代码中,put()方法自动更新了主键为1的记录。
3.7 删除数据
IDBObjectStore.delete()
方法用于删除记录。
function remove() {var request = db.transaction(['person'], 'readwrite').objectStore('person').delete(1);request.onsuccess = function (event) {console.log('数据删除成功');};
}remove();
3.8 使用索引
索引的意义在于,可以让你搜索任意字段,也就是说从任意字段拿到数据记录。如果不建立索引,默认只能搜索主键(即从主键取值)。
假定新建表格的时候,对name字段建立了索引。
objectStore.createIndex('name', 'name', { unique: false })
;
现在,就可以从name找到对应的数据记录了。
var transaction = db.transaction(['person'], 'readonly');
var store = transaction.objectStore('person');
var index = store.index('name');
var request = index.get('李四');request.onsuccess = function (e) {var result = e.target.result;if (result) {// ...} else {// ...}
}
浏览器储存之Cookie、sessionStorage、localStorage和indexedDB区别与详解相关推荐
- 浏览器存储,储存,Cookie,WebStorage,IndexedDB
前言: Cookie存储数据的功能已经很难满足开发所需,逐渐被WebStorage.IndexedDB所取代: 一.Cookie 什么是Cookie及应用场景 Cookie指网站为了储存一些信息,辨别 ...
- 浏览器本地存储Cookie、LocalStorage、SessionStorage
文章目录 浏览器本地存储 浏览器本地存储 浏览器本地存储方式 (1)Cookie Cookie 是最早被提出来的本地存储方式,在此之前,服务端是无法判断网络中的两个请求是否是同一用户发起的,为解决这个 ...
- session,cookie,sessionStorage,localStorage的区别及应用场景
浏览器的缓存机制提供了可以将用户数据存储在客户端上的方式,可以利用cookie,session等跟服务端进行数据交互. 一.cookie和session cookie和session都是用来跟踪浏览器 ...
- 浅谈session,cookie,sessionStorage,localStorage的区别及应用场景
浏览器的缓存机制提供了可以将用户数据存储在客户端上的方式,可以利用cookie,session等跟服务端进行数据交互. 一.cookie和session cookie和session都是用来跟踪浏览器 ...
- 计算机网络-自顶向下-Web应用2(Cookie、Web缓存、条件GET详解)
Web应用2 计算机网络所有笔记链接 Cookie技术 前面提到HTTP的服务是 无状态的,这简化了服务器的设计,但是Web站点还是很有必要具有能够识别用户的功能的.比如说你至少能够把我密码啥的记录了 ...
- html domin属性,cookie中的path与domain属性详解
1.domain表示的是cookie所在的域,默认为请求的地址,如网址为www.jb51.net/test/test.aspx,那么domain默认为www.jb51.net.而跨域访问,如域A为t1 ...
- 用PHP实现浏览器点击下载各种格式文档的方法详解【txt apk等等】
[[注:其他文件想设置成下载文件,和下面介绍的方法一致]] 由于现在的浏览器已经可以识别txt文档格式,如果只给txt文档做一个文字链接的话,点击后只是打开一个新窗口显示txt文件的内容,并不能实现点 ...
- rem适配的浏览器_[史上最全]UI相关尺寸单位详解 | px、pt、dp、sp、rem、vwvh、rpx、ppi、dpi、dppx...
先给进来看文章的你点个赞 尺寸适配应该由开发同事负责处理,处理不好是他的问题,你有兴趣了解这些让人头疼的事,证明你是共产主义好社畜,还有工作量不饱和,Good for you~适配问题是影响设计复现的 ...
- axios库读不到cookie_axios中cookie跨域及相关配置示例详解
自从入了vue之后,一直在用axios这个库来做一些异步请求,下面这篇文章主要介绍关于axios中cookie跨域及相关配置的资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考借鉴. 前言 最近 ...
最新文章
- 1012. 数字分类 java_PAT-B-1012. 数字分类(Java)
- LeetCode 111. Minimum Depth of Binary Tree--Java, Python解法--二叉树最小高度--迭代,递归
- python标准库学习9
- python程序员面试宝典 勘误_《前端面试江湖》勘误合集(二)
- 黑马lavarel教程---11、响应处理
- JAVA报错是一层一层的吗_Java异常处理:给程序罩一层保险
- 符号链接文件_Windows10下创建符号链接(SymbolicLink)
- mysql 2027_阿里云mysql远程登录报ERROR 2027(HY000)
- c# contains方法_C#/.Net Core/WPF框架初建(国际化、主题色)
- wms智能仓储系统不可缺少?
- 机器学习之工程师入门路线
- 怎么阻止acrobat自动更新升级?
- 用c语言小游戏代码大全,c语言经典游戏代码
- 和平精英微信和qq不是一个服务器,和平精英qq和微信能一起玩吗 qq微信数据互通吗...
- 基于node.js的网页聊天系统设计与实现
- Vue CLI构建SPA项目教你手把手创建SPA项目
- 用python完成选股策略a股_Python 金融: 0亏损选股策略
- 怎样找到ant压缩这个软件_PDF压缩到最小该怎么完成?这个PDF压缩软件最实用
- 高德地图2016清明出行交通预测报告(完整版)
- 潮汕牛肉火锅,美味在你身边
热门文章
- 【JavaScript】黑点捉红点并躲绿点游戏
- Redis社交应用里面之关注、粉丝、共同好友案例
- 木字楠后台管理系统开发(3):Vue项目初始化并引入基础依赖
- go语言实现最小区块链教程5-地址
- python发微信提醒天气冷了注意保暖_2019天气变冷的朋友圈说说 注意保暖的微信问候语...
- Devexpress控件使用皮肤,设置默认皮肤及动态换肤
- 华为蓝牙耳机推荐哪款好?佩戴舒适的无线耳机推荐
- Stratasys:光固化3d打印机优缺点论点,需品牌品质落实
- 【matlab数学建模】运用建立的模型分别为这四组游客设计旅行计划
- 披着羊皮的狼?表面看着是个轻薄本,可实际上却是个游戏本