? ? ? ? Web存储主要包含cookie、sessionStorage、localStorage和indexedDB(WebSQL已被废弃),本篇就这4种存储的知识点进行梳理和总结。
? ? ? ? cookie从开始是为了弥补HTTP协议无状态的不足而设计的。
????????用户第一次访问或登录时,服务端产生一个会话ID(就是一个身份ID),通过HTTP响应头Set-Cookie将会话ID带回给客户端,从响应头Set-Cookie取出会话ID,保存在浏览器中。后续HTTP请求通过请求头Cookie将会话ID带回给服务端,服务端就清楚知道来自哪个用户。
? ? ? ? 可以通过document.cookie取得cookie数据,可发现cookie数据的格式是字符串形式的,由许多个键值对组成,每对键值对由一个分号+一个空格分隔。注意: cookie数据是通过encodeURIComponent编码过的,需要decodeURIComponent解码得到原始cookie数据。
// 读取cookie
document.cookie;
'key1=value1; key2=value2; key3=value3......'
// 写入cookie
document.cookie = 'key4=value4;max-age=5;path=/';
// 删除cookie一条键值
document.cookie = 'key4=;max-age=0';
? ? ? 除了键值对数据,每个键值对还有:Domain、Path、Expires、Size、HttpOnly、Secure、SameSite、Partition Key、Priority,大家可以打开浏览器F12,点进应用(Application)中进行查看。
Cookie基本信息 | ||
字段名 | 中文释义 | 说明 |
Name | 键名 | <略> |
Value | 键值 | <略> |
Domain | 域名 | 网站所在的域名(不含端口) |
Path | 路径 | cookie的存储路径,默认是当前项目根路径 |
Expires/Max-Age | 失效时间 | cookie过期时间,什么时候过期,可以是时间节点Expires,也可以是多少秒Max-Age |
Size | cookie大小 | 一条键值对的大小,即Name的size + Value的size |
HttpOnly | 是否仅通过HTTP传输 | 某些重要cookie仅由后台设置,不可随意修改,可设置此标志 |
Secure | 安全标志 | 设置Secure标志后,这条键值对仅https请求才能携带 |
SameSite | 同站点 | 防止CSRF攻击和用户追踪的安全属性 |
Partition Key | <略> | |
Priority | 优先级 | |
Cookie优缺点 | ||
缺点 | 1. 存在安全问题,因为cookie中存储的身份认证信息容易被窃取 2. 存储数据大小问题,仅4KB 3. 每次HTTP都将cookie的所有参数,导致HTTP报文变大,请求变慢 |
? ? ? ? HTML5新增了会话存储sessionStorage和本地存储localStorage,二者都是Storage的实例化对象,均遵循同源策略,本篇先介绍一下Storage原型对象上的方法和属性,再总结一下二者的区别。
Storage原型对象的方法和属性 | ||
方法和属性 | 说明 | 示例 |
Storage.prototype .setItem(key, value) | 功能:设置键值对,key和value都会被隐式转换成string 输入:string, string 输出:无 | sessionStorage.seItem('a', 1); localStorage.seItem('A', 1); |
Storage.prototype .getItem(key) | 功能:通过键名key获取键值value 输入:string 输出:string | sessionStorage.getItem('a'); localStorage.getItem('A'); |
Storage.prototype .key(index) | 功能:传入索引,获取对应位置的键名key 输入:number | string 输出:string | sessionStorage.key(0); localStorage.key(0); |
Storage.prototype .removeItem(key) | 功能:根据键名key,删除键值对 输入:string 输出:无 | sessionStorage.removeItem('a'); localStorage.removeItem('A'); |
Storage.prototype.clear() | 功能:清空所有键值对 输入:无 输出:无 | sessionStorage.clear(); localStorage.clear(); |
Storage.prorotyp.length | 功能:获取键值对数量 输出:number | sessionStorage.length; localStorage.length; |
sessionStorage和localStorage的异同 | ||
相同 | 1. 均是Storage实例化对象,继承Storage.prototype的属性和方法 2. 遵循同源策略,同源下数据共享 3. 都有5M存储空间,且仅保存字符串类型数据 | |
不同 | 1. 失效时间 ① localStorage不会失效,关闭浏览器也不会失效,需要用户手动清除localStorage.clear() ② sesionStorage与页面会话绑定,页面会话失效,sessionStorage即失效,刷新页面不会失效 2. 作用范围 ① localStorage在同源情况下,跨页签也有效,可跨页签共享数据 ② sessionStorage仅当前页签有效 |
? ? ? ? HTML5还新增事务型的数据库indxedDB,可存储大量数据。indexedDB操作涉及的API比较多,但也不是太难,有兴趣同学可以网上查资料学习。本篇仅给出涉及的所有方法和属性。
4.1 IDBFactory原型对象的方法(indexedDB是IDBFactory的实例化对象)
IDBFfactory | ||
IDBFactory原型的方法和属性 | 描述 | 示例 |
IDBFactory.prototype.open() | 功能:打开或新建数据库 | <略> |
IDBFactory.prototype.databases() | <略> | <略> |
IDBFactory.prototype.deleteDatabase() | <略> | <略> |
IDBFactory.prototype.cmp() | <略> | <略> |
4.2 操作请求IDBOpenDBRequest和IDBRequest(IDBRequest继承于EventTarget)
操作请求IDBOpenDBRequest和IDBRequest | ||
原型的方法和属性 | 描述 | 示例 |
IDBRequest.prototype.result | <略> | <略> |
IDBRequest.prototype.onsuccess | <略> | <略> |
IDBRequest.prototype.onerror | <略> | <略> |
IDBRequest.prototype.transaction | <略> | <略> |
IDBRequest.prototype.source | <略> | <略> |
IDBRequest.prototype.error | <略> | <略> |
IDBRequest.prototype.readyState | <略> | <略> |
IDBOpenDBRequest.prototype.onupgradeneeded | <略> | <略> |
IDBOpenDBRequest.prototype.onblocked | <略> | <略> |
4.3 数据库IDBDataBase原型的的方法和属性
数据库IDBDatabase | ||
方法和属性 | 描述 | 示例 |
IDBDataBase.prototype.createObjectStore() | <略> | <略> |
IDBDataBase.prototype.deleteObjectStore() | <略> | <略> |
IDBDataBase.prototype.transaction() | 功能:新建事务 | <略> |
IDBDataBase.prototype.close() | <略> | <略> |
IDBDataBase.prototype.name | <略> | <略> |
IDBDataBase.prototype.objectStoreNames | <略> | <略> |
IDBDataBase.prototype.version | <略> | <略> |
IDBDataBase.prototype.onclose | <略> | <略> |
IDBDataBase.prototype.onabort | <略> | <略> |
IDBDataBase.prototype.onerror | <略> | <略> |
IDBDataBase.prototype.onversionchange | <略> | <略> |
4.4 仓库IDBObjectStore原型的方法和属性如下:
仓库对象IDBObjectStore | ||
方法和属性 | 描述 | 示例 |
IDBObjectStore.prototype.add() | 功能:写入一条数据 | <略> |
IDBObjectStore.prototype.delete(primaryKey) | 功能:根据主键删除一条数据 | <略> |
IDBObjectStore.prototype.clear() | <略> | <略> |
IDBObjectStore.prototype.put() | 功能:更新一条数据 | <略> |
IDBObjectStore.prototype.get(primaryKey) | 功能:根据主键查询一条数据 | <略> |
IDBObjectStore.prototype.getAll() | <略> | <略> |
IDBObjectStore.prototype.getKey() | <略> | <略> |
IDBObjectStore.prototype.getAllKeys() | <略> | <略> |
IDBObjectStore.prototype .createIndex(index, property, options) | 功能:新建索引 | <略> |
IDBObjectStore.prototype.deleteIndex() | <略> | <略> |
IDBObjectStore.prototype.index() | <略> | <略> |
IDBObjectStore.prototype.openCursor() | 功能:打开一个游标cursor | <略> |
IDBObjectStore.prototype.openKeyCursor() | <略> | <略> |
IDBObjectStore.prototype.count() | <略> | <略> |
IDBObjectStore.prototype.name | <略> | <略> |
IDBObjectStore.prototype.keyPath | <略> | <略> |
IDBObjectStore.prototype.autoIncrement | <略> | <略> |
IDBObjectStore.prototype.indexNames | <略> | <略> |
IDBObjectStore.prototype.transaction | <略> | <略> |
?4.5 索引IDBIndex原型的方法和属性
索引IDBIndex | ||
方法和属性 | 描述 | 示例 |
IDBIndex.prototype.get(index) | 功能:通过索引获取一条数据 | <略> |
IDBIndex.prototype.getAll() | <略> | <略> |
IDBIndex.prototype.getKey() | <略> | <略> |
IDBIndex.prototype.getAllKeys() | <略> | <略> |
IDBIndex.prototype.openCursor() | <略> | <略> |
IDBIndex.prototype.openKeyCursor() | <略> | <略> |
IDBIndex.prototype.count() | <略> | <略> |
IDBIndex.prototype.objectStore | <略> | <略> |
IDBIndex.prototype.name | <略> | <略> |
IDBIndex.prototype.keyPath | <略> | <略> |
IDBIndex.prototype.unique | <略> | <略> |
IDBIndex.prototype.multiEntry | <略> | <略> |
4.6 事务IDBTransaction原型的方法和属性
事务IDBTransaction | ||
方法和属性 | 描述 | 示例 |
IDBTransaction.prototype.commit() | <略> | <略> |
IDBTransaction.prototype.abort() | <略> | <略> |
IDBTransaction.prototype.objectStore() | 功能:获取IDBObjectStore对象 | <略> |
IDBTransaction.prototype.db | <略> | <略> |
IDBTransaction.prototype.objectStoreNames | <略> | <略> |
IDBTransaction.prototype.mode | <略> | <略> |
IDBTransaction.prototype.durability | <略> | <略> |
IDBTransaction.prototype.oncomplete | <略> | <略> |
IDBTransaction.prototype.onerror | <略> | <略> |
IDBTransaction.prototype.onabort | <略> | <略> |
IDBTransaction.prototype.error | <略> | <略> |
4.7 指针IDBCursor原型的方法和属性
指针IDBCursor | ||
方法和属性 | 描述 | 示例 |
IDBCursor.prototype.advance() | <略> | <略> |
IDBCursor.prototype.delete() | <略> | <略> |
IDBCursor.prototype.update() | <略> | <略> |
IDBCursor.prototype.direction | <略> | <略> |
IDBCursor.prototype.continue() | <略> | <略> |
IDBCursor.prototype.continuePrimaryKey() | <略> | <略> |
IDBCursor.prototype.key | <略> | <略> |
IDBCursor.prototype.primaryKey | <略> | <略> |
IDBCursor.prototype.request | <略> | <略> |
IDBCursor.prototype.source | <略> | <略> |
4.8 主键集合IDBKeyRange原型的方法和属性
主键集合IDBKeyRange | ||
方法和属性 | 描述 | 示例 |
IDBKeyRange.prototype.includes() | <略> | <略> |
IDBKeyRange.prototype.upper | <略> | <略> |
IDBKeyRange.prototype.lower | <略> | <略> |
IDBKeyRange.prototype.upperOpen | <略> | <略> |
IDBKeyRange.prototype.lowerOpen | <略> | <略> |
const request = indexedDB.open('test', 1);
request.onerror = (err) => {
console.log(err);
}
request.onsuccess = (event) => {
const db = request.result;
}
request.onupgradeneeded = (event) => {
const db = event.target.result;
let objectStore;
if(!db.objectStoreNames.contains('person')) {
objectStore = db.createObjectStore('person', { keyPath: 'id' });
}
}
? ? ? ?随差浏览器的发展,Web可以做的事情也会越来越多,Web3D、GIS以及其他PC端应用都有可能搬到Web上,它们均会涉及大量数量的处理和存储,Web存储为Web客户端在处理大量数据方面也变得很便利。
注:以上,如有不合理之处,还请帮忙指出,大家一起交流学习~