localStorage
localStorage 属于本地存储,替代了之前的userData(userdata仅用于IE浏览器)
生命周期:保存的数据将永久存在,除非被手动删除。
存放空间大小:一般为5MB(不同浏览器可能存在差异)。
与服务器通信:仅在浏览器中保存,不参与服务器的通信。
应用场景:替代了传统cookie管理购物车的工作,同时适用于保存游戏产生的一些本地数据。
易用性:原生接口是可以直接使用的,支持开发人员再次封装object和array
sessionStorage
sessionStorage同localStorage类似,存储方式也是属于本地存储
生命周期:仅在当前会话有效,关闭页面或者浏览器后会被清除。
存放空间大小:一般为5MB(不同浏览器可能存在差异)。
与服务器通信:仅在浏览器中保存,不参与服务器的通信。
应用场景:敏感账号一次性登录。
易用性:原生接口是可以直接使用的,支持开发人员再次封装object和array!
localStorage和sessionStorage的使用
localStorage和sessionStorage具有相同的接口
setItem (key, value) —— 保存数据,以键值对的方式储存信息。
getItem (key) —— 获取数据,将键值传入,即可获取到对应的value值。
removeItem (key) —— 删除单个数据,根据键值移除对应的信息。
clear () —— 删除所有的数据 。
key (index) —— 获取某个索引的key。
cookie
生命周期:一般由服务器生成,可设置失效时间,若在浏览器生成,则默认为浏览器的会话期间。
存放空间大小:cookie 确实体现了小甜饼的特性,它的大小限制为4KB左右。
与服务器通信:每次都会携带在HTTP头中,若数据太大则会导致响应慢性能问题。
应用场景:保存用户的登陆信息。针对登录过的用户,服务器会在登陆时在cookie中插入一段加密的唯一的辨识码,下次即可通过读取加密码判断当前用户登录情况。
安全性:在使用Cookie、localStorage 和 sessionStorage 的时候,需要时刻注意是否有代码存在 XSS 注入的风险。为避免可通过打开控制台的方式随意修改值,因此以上方式不适用于存放敏感数据。
易用性:cookie的原生接口不友好,通常需要开发人员自己封装。
IndexedDB
是一种在浏览器端存储数据的方式,是因为它丰富了客户端的查询方式,由于是本地存储,可以有效的减少网络对页面数据的影响。
特点:
1)对象仓库(objectStore):
indexedDB没有表的概念,而是使用objectStore。一个数据库中可以包含多个objectStore。objectStore是一个灵活的数据结构,可以存放多种类型数据,也就是说一个objectStore相当于一张表,里面储存的每条数据和一个键相关。我们可以使用每条记录中的某个字段作为键值(keyPath),也可以使用自动生成的递增数字作为键值(keyGenerator),也可以不指定。选择键的类型不同,objectStore可以存储的数据结构也有差异。
2)事务性:
indexedDB中,每一个对数据库操作是在一个事务的上下文中执行的。事务范围一次影响一个或多个objectstores。你通过传入一个objectstores名字的数组到创建事务 范围的函数来定义
比如:db.transaction( storeName, ’ readwrite’ ),创建事务的第二个参数是事务模式,当请求一个事务时,必须决定是按照只读还是读写模式模式请求访问
3)基于请求:
对indexedDB数据库的每次操作,描述为通过一个请求打开数据库,访问一个objectStore,再继续。indexedDB API天生是基于请求的,这也是API异步本性指示,对于你在数据库执行的每次操作,你必须首先为这个操作创建一个请求,当请求完成,你可以响应由请求结果产生的事件和错误
4)异步:
在indexedDB 大部分操作并不是我们常用的调用方法,返回结果的模式,而是请求-响应的模式,所谓异步API是指并不是这条指令执行完毕,我们就可以使用 request.result 来获取 indexedDB 对象了。
类似于 我们使用ajax一样,语句执行完并不代表已经获取到了对象,所以我们一般在其回调函数中处理。
使用步骤及方法:
1) 判断浏览器是否支持indexedDB
var indexedDB = window.indexedDB || window.WebKitIndexedDB || window.mozIndexedDB || window.msIndexedDB;
if (!indexedDB) {
console.log('你的浏览器不支持indexedDB');
}
2)打开数据库
// open这个方法接收两个参数,一个是数据库的名称,没有即新建,另一个是数据库版本,默认1
var openDBRequest = window.indexedDB.open("MyTestDatabase", 3);
3)添加处理函数
打开数据库后,若顺利则一个 success 事件(即一个 type 属性被设置成“success”的DOM事件)会被触发,使用 request 作为它的 target,success被触发的话,相关的 request 的 onsuccess() 函数就会被触发,使用 success 事件作为它的参数。否则,如果不是所有事情都成功的话,一个 error 事件(即 type 属性被设置成 “error” 的 DOM 事件) 会在 request 上被触发。这将会触发使用 error 事件作为参数的 onerror() 方法。
openDBRequest.onerror = function(event) {
// do something with request.errorCode
console.log('error', event);
}
openDBRequest.onsuccess = function(event) {
// do something with request.result
console.log('success', event);
}
4)创建和更新数据库版本号
更新数据库就是创建或者删除对象存储空间,需要实现 onupgradeneeded 处理程序,这个处理程序将会作为一个允许你处理对象存储空间的 versionchange 事务的一部分被调用,在onupgradeneeded处理程序中,openDBRequest的result属性是IDBDatabase类型。在数据库第一次被打开时或者当指定的版本号高于当前被持久化的数据库的版本号时,这个 versionchange 事务将被创建。版本号是个 unsigned long long 数字,即一个非常大的整数。
openDBRequest.onupgradeneeded = function(event) {
// 更新对象存储空间和索引
console.log('upgradeneeded', event);
}
5)构建数据库
IndexedDB 使用对象存储空间而不是表,并且一个单独的数据库可以包含任意数量的对象存储空间。每当一个值被存储进一个对象存储空间时,它会被和一个键相关联。键的提供可以有几种不同的方法,这取决于对象存储空间是使用 key path 还是 key generator。也可以使用对象存储空间持有的对象,不是基本数据类型,在任何对象存储空间上创建索引。索引可以让你使用被存储的对象的属性的值来查找存储在对象存储空间的值,而不是用对象的键来查找。
const customerData = [
{ssn: "111-222-333", name: "zuo", age: 21, email: "8848156@163.com"},
{ssn: "444-555-666", name: "bert", age: 21, email: "8848156@163.com"},
];
const dbName = "the_name";
var request = indexedDB.open(dbName, 2);
request.onerror = function(event) {
// do something with request.result
}
request.onupgradeneeded = function(event) {
// request(即event.target)的result属性是IDBDatabase类型
var db = event.target.request;
// 创建一个对象存储空间来持有有关客户信息
// 将使用的ssn作为key path 保证唯一性
// createObjectStore()方法返回的是IDBObjectStore类型的对象
var objectStore = db.createObjectStore("customers", {keyPath: "ssn"});
// 创建一个索引来通过name搜索客户
// 可能存在重复,不能使用unique索引
objectStore.createIndex("name", "name", {unique: true});
// 创建一个索引来通过email搜索客户
// 可能存在不同的两个客户使用相同的email地址,因此使用一个unique索引
objectStore.createIndex("email", email, {unique: false});
// 在新创建的对象存储空间中保存值
for(var i in customerData) {
objectStore.add(customerData[i]);
}
}
onupgradeneeded 是我们唯一可以修改数据库结构的地方。我们可以在onupgradeneeded创建和删除对象存储空间以及构建和删除索引。对象存储空间仅调用 createObjectStore() 就可以创建。这个方法使用存储空间的名称,和一个对象参数。即便这个参数对象是可选的,它还是非常重要的,因为它可以让你定义重要的可选属性和完善你希望创建的对象存储空间的类型。
6)增删改查
a、创建数据库并增加读写权限:
// transaction()方法返回的是IDBTransaction类型的对象
var transaction = db.transaction(["customers", readwrite]);
// 注意: 旧版实验性的实现使用不建议使用的常量 IDBTransaction.READ_WRITE 而不是 "readwrite"
// 如果你想支持这样的实现, 你只要这样写就可以了:
var transaction = db.transaction(["customers"], IDBTransaction.READ_WRITE);
b、添加数据库
// 当所有的数据都被增加到数据库时执行一些操作
transaction.oncomplete = function(event) {
console.log('all done');
}
transaction.onerror = function(event) {
// Don't forget error handling
}
// 因为transaction可以跨越多个对象存储空间(IDBObjectStore类型的对象),所以,当需要获取特定的对象存储
var objectStore = transaction.objectStore("customers");
for(var i in customerData) {
var request = objectStore.add(customerData[i]);
request.onsuccess = function(event) {
// event.target.result == customerData[i].ssn
};
}
c、删除数据库
var request = objectStore.delete("111-222-333");
request.onsuccess = function(event) {
// 删除数据成功
}
d、获取数据库中内容
var request = objectStore.get("444-555-666");
request.onerror = function() {
// 错误处理
}
request.onsuccess = function(event) {
// 对request.result 做些操作
console.log('name for ssn 444-555-666 is', request.result.name);
}
e、游标法遍历数据库中的值:
// openCursor()方法返回一个IDBRequest类型的请求对象cursorRequest,如果请求对象cursorRequest成功
var cursorRequest = objectStore.openCursor();cursorRequest.onsuccess = function(event) {
// cursorRequest的result属性是IDBCursorWithValue类型的对象
var cursor = event.target.result;
if(cursor) {
console.log('name for ssn' + cursor.key + "is" + cursor.value.name);
cursor.continue();
} else {
console.log('no more entries');
}
}
注:一般情况下,每个游标只发起一次请求。要想发起另一次请求,必须调用游标的下面2个方法之一:
continue(key):移动到结果集中的下一项。参数 key 是可选的,不指定这个参数,游标移动 到下一项;指定这个参数,游标会移动到指定键的位置;
advance(count):向前移动 count 指定的项数。
这两个方法都会导致游标使用相同的请求,因此相同的onsuccess和onerror事件处理程序也会得到重用。
另外,indexedDB有更方便的使用,采用的第三方库dexie,可以参考文章:indexedDB愉快使用体检,dexie二次封装
webSql
Web SQL 数据库 API 是一个独立的规范,其引入了一组使用 SQL 操作客户端数据库的 APIs,它不属于 HTML5 规范的一部分。
核心方法
1、openDatabase:这个方法使用现有的数据库或者新建的数据库创建一个数据库对象。
2、transaction:这个方法让我们能够控制一个事务,以及基于这种情况执行提交或者回滚。
3、executeSql:这个方法用于执行实际的 SQL 查询。