图片 10

主旨使用

indexedDB 基本使用

2017/12/14 · 基础本领 ·
1 评论 ·
IndexedDB

初稿出处:
党黎明   


indexedDB简介:

indexedDB
是大器晚成种接纳浏览器存款和储蓄多量数量的方法.它成立的数据足以被询问,并且能够离线使用.

 

indexedDB 有以下特点:

  1. indexedDBWebSQL 数据库的替代品
  2. indexedDB安分守己同源契约(只可以访谈同域中存放的数量,而无法访谈别的域的)
  3. API包含异步API同步API三种:许多景况下使用异步API;
    同步API必须同
    WebWorkers
    一齐利用, 近些日子尚未浏览器扶植同步API
  4. indexedDB 是专门的工作方式的数据库, 使用 key-value 键值对积累数据
  5. indexedDB 不应用结构化查询语言(SQL).
    它经过索引(index)所产生的指针(cursor)来成功查询操作

介绍

IndexedDB就是二个数据库
其最大的表征是:
应用对象保存数据,并不是接受表来保存数据,同期,它是异步的

后生可畏、使用indexedDB的基本情势

  1. 开拓数据库并且开首一个作业。
  2. 创造一个 objecStore
  3. 营造三个乞求来实践一些数据库操作,像扩充或提取数据等。
  4. 经过监听正确类型的 DOM 事件以等待操作完结。
  5. 在操作结果上进展部分操作(能够在 request 对象中找到卡塔尔国

行使办法

二、创制、张开数据库

indexedDB 存在于全局对象window上, 它最主要的三个办法正是open艺术,
该办法选拔多少个参数:

  • dbName // 数据库名称 [string]
  • version // 数据库版本 [整型number]

var DB_NAME = ‘indexedDB-test’, VERSION = 1, db; var request =
indexedDB.open(DB_NAME, VE3 WheelerSION); request.onsuccess = function(event) {
db = event.target.result; // console.log(event.target === request); //
true db.onsuccess = function(event) { console.log(‘数据库操作成功!’); };
db.onerror = function(event) { console.error(‘数据库操作产生错误!’,
event.target.errorCode); }; console.log(‘展开数据库成功!’); };
request.onerror = function(event) { console.error(‘创立数据库出错’);
console.error(‘error code:’, event.target.errorCode); };
request.onupgradeneeded = function(event) { // 更新目的存款和储蓄空间和目录
…. };

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var DB_NAME = ‘indexedDB-test’, VERSION = 1, db;
var request = indexedDB.open(DB_NAME, VERSION);
request.onsuccess = function(event) {
    db = event.target.result;
    // console.log(event.target === request); // true
    db.onsuccess = function(event) {
        console.log(‘数据库操作成功!’);
    };
    db.onerror = function(event) {
        console.error(‘数据库操作发生错误!’, event.target.errorCode);
    };
    console.log(‘打开数据库成功!’);
};
request.onerror = function(event) {
    console.error(‘创建数据库出错’);
    console.error(‘error code:’, event.target.errorCode);
};
request.onupgradeneeded = function(event) {
   // 更新对象存储空间和索引 ….
};

倘若本域下一纸空文名称为DB_NAME的数据库,则上述代码会创设二个名字为DB_NAME、版本号为VERSION的数据库;
触发的事件依次为: upgradeneededsuccess.

例如已存在名字为DB_NAME的数据库, 则上述代码会展开该数据库;
只触及success/error事件,不会触发upgradeneeded事件.
db是对该数据库的援用.

总是数据库

要采纳它必得先展开,通过 indexDB.open(name, version)办法展开一个数据库

  • name : 表示数据要开采的数据库的名目
  • version:为开采数据库的本子号

三、创造对象存款和储蓄空间和目录

在关系型数据库(如mysql)中,二个数据库中会有多张表,每张表有分其余主键、索引等;

key-value型数据库(如indexedDB)中,
三个数据库会有几个指标存款和储蓄空间,各种存款和储蓄空间有和好的主键、索引等;

创造对象存款和储蓄空间的操作日常位于创立数据库成功回调里:

request.onupgradeneeded = function(event) { // 更新目的存款和储蓄空间和目录
…. var database = event.target.result; var objectStore =
database.createObjectStore(“movies”, { keyPath: “id” });
objectStore.createIndex(‘alt’, ‘alt’, { unique: true });
objectStore.createIndex(‘title’, ‘title’, { unique: false }); };

1
2
3
4
5
6
request.onupgradeneeded = function(event) { // 更新对象存储空间和索引 ….
    var database = event.target.result;
    var objectStore = database.createObjectStore("movies", { keyPath: "id" });
    objectStore.createIndex(‘alt’, ‘alt’, { unique: true });
    objectStore.createIndex(‘title’, ‘title’, { unique: false });
};

图片 1

onupgradeneeded
是大家唯意气风发能够改进数据库结构之处。在此此中,咱们得以成立和删除对象存款和储蓄空间以致营造和删除索引。

在数据库对象database上,有以下办法可供调用:

  1. createObjectStore(storeName, configObj) 创制几个对象存款和储蓄空间
    • storeName // 对象存款和储蓄空间的名称 [string]
    • configObj // 该对象存储空间的布署 [object]
      (在那之中的keyPath属性值,标志对象的该属性值唯风流罗曼蒂克)
  2. createIndex(indexName, objAttr, configObj) 创立多个目录
    • indexName // 索引名称 [string]
    • objAttr // 对象的属性名 [string]
    • configObj // 该索引的铺排对象 [object]

indexDB.open()措施的法规

分为三种情景:
1. 无胫而行的数据库不设有
当传入的数据库不设一时,该方法就可以制造叁个名字为name的数据库,并打开它,那时候,会先触发upgradeneeded事件;调用该函数会重回一个IDBRequest指标,能够在该对象上加多onsuccess事件onerror事件
注意:当展开二个不真实的数据库时会触发upgradeneeded事件,那是触发该事件的大器晚成种门路,为何会触发该事件吧?该事件有怎样效劳?留个疑问在那刻,等会解答。

2. 扩散的数据库存在
那边分为二种境况:

  • 当传入的数据仓库储存在,且version版本号与将要打开的数据库版本号也相像
    则一贯展开该数据库,如若成功,则会触发onsuccess事件,战败则触发onerror事件
    注意:这里并不会触发upgradeneeded事件,为啥?留个问号

  • 当传入的数据仓库储存在,可是传入的version版本号高于将在展开的数据库的本子号
    则平素打开该数据库,同不经常候触发upgradeneeded事件,然后再接触onsuccess事件onerror事件,这里也触发了onupdateneeded事件

四、增删数据

对数据库的操作(增加和删除查改等)都需求经过事务来完成,事务装有二种形式:

  • readonly 只读(能够并发进行,优先利用)
  • readwrite 读写
  • versionchange 版本改进

upgradeneeded事件

触发该事件的规格:当展开的数据库空中楼阁,或许传播的数据库版本version高于当前版本,则会触发该事件

upgradeneeded事件的意义:当展开了叁个数据库之后,要求开采三个名叫:目的存款和储蓄空间
的实物(能够知晓为多少便是寄放在这里个空间里面,叁个数据库能够创设多少个对象存款和储蓄空间卡塔 尔(阿拉伯语:قطر‎,而
对象存储空间 只能在upgradeneeded事件的管理函数中开创

利用时,注意以下二种意况:

  1. 当大家首先次打开成立数据库时,会触发upgradeneeded事件,大家就供给在里头成立对象存款和储蓄空间

  2. 当大家对数据库版本进行更新时,也会触发该事件,此时能够在那创设新的对象存款和储蓄空间,原来的指标存款和储蓄空间依然存在

注意:风度翩翩经供给对指标存款和储蓄空间扩充改造,那么只好先将积累在它里面包车型客车多寡读抽出来,再将其删除,然后使用新的选项去创立它,再写入原本的数码

开垦数据库并创立对象存款和储蓄空间的代码:

// 对于该API,各浏览器还未同一,所以需要对一些接口添加前缀
window.indexedDB = window.indexedDB || window.msIndexedDB || window.mozIndexedDB || window.webkitIndexedDB;
window.IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction || window.msIDBTransaction || {READ_WRITE: "readwrite"};
window.IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange || window.msIDBKeyRange;
window.IDBCursor = window.IDBCursor || window.webkitIDBTransaction;

// 判断浏览器是否支持IndexedDB
if (!window.indexedDB) {
window.alert("Your browser doesn't support a stable version of IndexedDB.")
}

var request , db;
// 打开或创建 名为dbName的数据库
request = window.indexedDB.open('dbName', 2)
request.onsuccess = function (event) {
   db = event.target.result;
}

request.onerror = function (event) {
   console.log('错误代码: ' + event.target.errorCode);
}

request.onupgradeneeded = function(event) {
  db = event.target.result;  // 
  // 创建一个   对象存储空间,名为customers
  var objectStore = db.createObjectStore('customers', {keyPath: 'ssn'});
  // 对于某些数据,可以为一个对象存储空间指定多个键。比如,若要通过用户ID 和用户名 两种方式来保存用户资料,就需要通过两个键来存取记录
  // 因此可以使用createIndex,名字是有可能重复的,所以其unique 设置为 false ;第一个name是索引的名字,该名字是索引的名字,第二个name是索引的属性的名字,该名字要与对象中的属性相同
  objectStore.createIndex('name', 'name', { unique: false});

  // 创建一个email的索引,该email是独特的,所以 unique 设置为 true
  objectStore.createIndex('email', 'email', { unique: true});
}

向数据库中扩张数量

前边提到,扩大数据需求经过事务事务的施用方法如下:

var transaction = db.transaction([‘movies’], ‘readwrite’);
transaction.oncomplete = function(event) { console.log(‘事务完毕!’); };
transaction.onerror = function(event) { console.log(‘事务失利!’,
event.target.errorCode); }; transaction.onabort = function(event) {
console.log(‘事务回滚!’); };

1
2
3
4
5
6
7
8
9
10
var transaction = db.transaction([‘movies’], ‘readwrite’);
transaction.oncomplete = function(event) {
    console.log(‘事务完成!’);
};
transaction.onerror = function(event) {
    console.log(‘事务失败!’, event.target.errorCode);
};
transaction.onabort = function(event) {
    console.log(‘事务回滚!’);
};

图片 2数据库对象的transaction()艺术选拔多个参数:

  • storeNames //
    对象存款和储蓄空间,能够是指标存款和储蓄空间名称的数组,也能够是单个对象存款和储蓄空间名称,必传
    [array|string]
  • mode // 事务形式,上面提到的两种之大器晚成,可选,默许值是readonly
    [string]

这么,大家得到三个业务对象transaction, 有二种事件恐怕会被触发:
complete, error, abort.
今后,大家透过职业向数据库indexedDB-test
对象存款和储蓄空间movies中插入数据:

var objectStore = transaction.objectStore(‘movies’); // 钦点对象存款和储蓄空间
var data = [{ “title”: “寻梦环游记”, “year”: “2017”, “alt”:
“”, “id”: “20495023” }, {
“title”: “你在哪”, “year”: “2016”, “alt”:
“”, “id”: “26639033” }, {
“title”: “笔仙咒怨”, “year”: “2017”, “alt”:
“”, “id”: “27054612” }];
data.forEach(function(item, index){ var request = objectStore.add(item);
request.onsuccess = function(event) { console.log(‘插入成功!’, index);
console.log(event.target.result, item.id); //
add()方法调用成功后result是被拉长的值的键(id) }; });

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
var objectStore = transaction.objectStore(‘movies’);  // 指定对象存储空间
var data = [{
  "title": "寻梦环游记",
  "year": "2017",
  "alt": "https://movie.douban.com/subject/20495023/",
  "id": "20495023"
}, {
  "title": "你在哪",
  "year": "2016",
  "alt": "https://movie.douban.com/subject/26639033/",
  "id": "26639033"
}, {
  "title": "笔仙咒怨",
  "year": "2017",
  "alt": "https://movie.douban.com/subject/27054612/",
  "id": "27054612"
}];
data.forEach(function(item, index){
    var request = objectStore.add(item);
    request.onsuccess = function(event) {
        console.log(‘插入成功!’, index);
        console.log(event.target.result, item.id); // add()方法调用成功后result是被添加的值的键(id)
    };
});

图片 3

经过作业对象transaction,在objectStore()主意中钦定对象存款和储蓄空间,就获得了能够对该目的存款和储蓄空间扩充操作的对象objectStore.

向数据库中追增添少,add()艺术扩充的指标,要是数据库中已存在同样的主键,也许唯风度翩翩性索引的键值重复,则该条数据不会插入进去;

充实多少还或然有三个主意: put(),
使用方法和add()差异的地方在于,数据库中若存在相通主键或然唯生机勃勃性索引重复,则会更新该条数据,不然插入新数据。

储存数据

积存数占有二种办法:add()方法put()方法

那二种办法的分歧首要体今后:当要增多数据的靶子存款和储蓄空间中早就存在有相同键的数量时,使用add()方法加多数据会报错误,而put()方法规会对现存数量实行翻新,所以add()方法平日用于初叶化数据,而put()方法用于立异数据

代码如下:

// customerData 为要存储的数据
const customerData = [{ ssn: '444-44-4444', name: 'AAA', age: 35, email: '[AAA@company.com](mailto:AAA@company.com)'},{ ssn: '666-66-6666', name: 'CCC', age: 35, email: '[CCC@company.com](mailto:CCC@company.com)'},{ ssn: '777-77-7777', name: 'DDD', age: 32, email: '[DDD@home.org](mailto:DDD@home.org)'},{ ssn: '555-55-5555', name: 'BBB', age: 32, email: '[BBB@home.org](mailto:BBB@home.org)'},
];

// 创建一个事务,该事务将要对名为“customers”的对象存储空间进行 read和write 操作,并返回事务索引
let transaction = db.transaction('customers', 'readwrite'); 

// 取得索引后,使用objectStore()方法并传入存储空间的名称,就可以访问特定的存储空间,这两步是必须的
let store = transaction.objectStore('customers'); 

// 添加数据到数据库中
for (var i in customerData) {
  // 返回的req也是一个对象,可以为其添加onsuccess和onerror事件,来检测数据是否添加成功
  let req = store.put(customerData[i]);   // 往一个存储空间中添加数据

}
// 判断事务整个操作完成
transaction.oncomplete = function(event) {
  console.log(event.target);
  alert('存储数据完成');
};
}

如上就将数据存款和储蓄到数据库dbNames的customers对象存款和储蓄空间中

上边代码中涉及了
[事务],这里先记住:举凡涉及到对数据库的读写删除操作,都亟需通过
[事务] 来完成

从数据库中删去数据

去除数据利用delete主意,同上近似:

var request = db.transaction([‘movies’], ‘readwrite’)
.objectStore(‘movies’) .delete(‘27054612’); // 通过键id来删除
request.onsuccess = function(event) { console.log(‘删除成功!’);
console.log(event.target.result); };

1
2
3
4
5
6
7
8
var request =
    db.transaction([‘movies’], ‘readwrite’)
      .objectStore(‘movies’)
      .delete(‘27054612’);  // 通过键id来删除
request.onsuccess = function(event) {
    console.log(‘删除成功!’);
    console.log(event.target.result);
};

 

政工和询问操作数据

最简单易行的始建筑工程作的方法是:
var transaction = db.transaction(); // db就是前面的数据库对象
这种办法成立的政工,只可以读取数据库中保存的兼具目的

诚如用法是:
var transaction = db.transaction('customes', 'readwrite');
代表只加载customers对象存款和储蓄空间中的数据,并且是以可读可写的法子加载

譬如不传第二个参数,则意味着只可访谈,不可改过;

此处重回的transaction是事情的目录

然后使用objectStore()艺术并传播对象存款和储蓄空间的称谓,就足以访谈特定的囤积空间了;

如下:

let transaction = db.transaction('customers', 'readwrite'); 
let store = transaction.objectStore('customers'); 

收获了地点的store后,大家能够动用如下方法对数据实行操作:

  • add()和put()方法:用于存储数据
    let req = store.add(data);
  • get(key)方法:获取键为key的指标
    let req = store.get(key);
  • delete(key)方法:删除键为key的靶子
    let req = store.delete(key);
  • clear()方法:清空对象存款和储蓄空间中的全部目的
    let req = store.clear();
    应用上述方法会重临两个对象,通过对其增多onsuccess和onerror事件,能够检查评定操作是还是不是成功

注意:通过oncomplete事件目的,访谈不到get()央浼再次回到的别样数据,必需在响应恳求的onsuccess事件管理程序中工夫访谈到数量

从数额中获取数据

获取数据使用get艺术,同上看似:

var request = db.transaction(‘movies’) .objectStore(‘movies’)
.get(‘9999682’); // 通过键alt来获得 request.onsuccess = function(event)
{ console.log(‘获取成功!’, event.target.result); };

1
2
3
4
5
6
7
var request =
    db.transaction(‘movies’)
       .objectStore(‘movies’)
       .get(‘9999682’);  // 通过键alt来获取
request.onsuccess = function(event) {
    console.log(‘获取成功!’, event.target.result);
};

应用游标查询数据

行使工作能够平素通过
已知的键检索单个对象。而在必要索求多少个指标时,则需求在业务内创设游标。

游标并不会提早收罗结果,游标先指向结果中的第生龙活虎项,在收到查找下大器晚成项的下令时,才会指向下意气风发项

如下:

let transaction = db.transaction('customers', 'readwrite'),
let store = transaction.objectStore('customers'),
let request = store.openCursor(null) ; // 这里创建游标
request.onsuccess = function (event) {
  // event.target.result 中保存的是在存储空间中查询到的对象
  // event.target.result 中有几个属性值,可以了解到查询到的对象中的细节,
  // key: 当前访问的对象的键
  // value:当前访问的实际对象
  // primaryKey: 游标使用的键
  // direction:数值,表示游标移动的方向
  let cursor = event.target.result;
  let value, updateRequest, deleteRequest;

  // 这里必须要检查游标中是否有数据
  if (cursor) {
    if (cursor.key === '555-55-5555') {
      value = cursor.value;   // 获取到实际的访问对象
      value.name = 'hexon';   // 修改对象的name属性
      // 调用update()方法可以用指定的对象,更新对象的value
      updateRequest = cursor.update(value);     
      updateRequest.onsuccess = function() {
          // 处理成功
       }
    }
    cursor.continue() ;  // 移动到下一项,会触发下一次请求,同时成功则触发request.onsuccess
  }
}

地方例子中,能够动用cursor.delete()方式删除当前项

五、使用索引

在头里,大家创造了五个目录alttitle,
配置对象里面包车型地铁unique质量标记该值是或不是唯生机勃勃

现今大家想找到alt属性值为https://movie.douban.com/subject/26639033/的对象,就足以选取索引。

var alt = ”; var objectStore
= db.transaction(‘movies’).objectStore(‘movies’); // 张开对象存款和储蓄空间
var index = objectStore.index(‘alt’); // 使用索引’alt’ var request =
index.get(alt); // 创设一个寻找数据的号令 request.onsuccess =
function(event) { console.log(‘The result is:’, event.target.result); };
var noDataTest = index.get(‘testalt’); // 未有该对象时的测试noDataTest.onsuccess = function(event) { console.log(‘success! result:’,
event.target.result); }; noDataTest.onerror = function(event) {
console.log(‘error! event:’, event); };

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var alt = ‘https://movie.douban.com/subject/26639033/’;
var objectStore = db.transaction(‘movies’).objectStore(‘movies’);  // 打开对象存储空间
var index = objectStore.index(‘alt’);  // 使用索引’alt’
var request = index.get(alt);          // 创建一个查找数据的请求
request.onsuccess = function(event) {
    console.log(‘The result is:’, event.target.result);
};
var noDataTest = index.get(‘testalt’);  // 没有该对象时的测试
noDataTest.onsuccess = function(event) {
    console.log(‘success! result:’, event.target.result);
};
noDataTest.onerror = function(event) {
    console.log(‘error! event:’, event);
};

图片 4

运用唯生机勃勃性索引,大家得以获取唯风姿浪漫的一条数据(大概undefined),那么使用非唯生龙活虎性索引呢?
我们向数据库中插入一条数据,使title重复:

db.transaction(‘movies’, ‘readwrite’).objectStore(‘movies’) .add({ alt:
”, title: ‘寻梦环游记’,
year: ‘2017’, id: ‘123456789’ }) .onsuccess = function(event) {
console.log(‘插入成功!’); };

1
2
3
4
5
6
7
db.transaction(‘movies’, ‘readwrite’).objectStore(‘movies’)
.add({ alt: ‘https://movie.douban.com/subject/27054612121/’,
    title: ‘寻梦环游记’,
    year: ‘2017’,
    id: ‘123456789’
})
.onsuccess = function(event) { console.log(‘插入成功!’); };

动用索引title获取title值为寻梦环游记的对象:

var indexName = ‘title’, title = ‘寻梦环游记’; var objectStore =
db.transaction(‘movies’).objectStore(‘movies’); var index =
objectStore.index(indexName); // 使用索引’alt’ var request =
index.get(title); // 成立二个找寻数据的须求 request.onsuccess =
function(event) { console.log(‘The result is:’, event.target.result); };

1
2
3
4
5
6
7
var indexName = ‘title’, title = ‘寻梦环游记’;
var objectStore = db.transaction(‘movies’).objectStore(‘movies’);
var index = objectStore.index(indexName);  // 使用索引’alt’
var request = index.get(title);          // 创建一个查找数据的请求
request.onsuccess = function(event) {
    console.log(‘The result is:’, event.target.result);
};

图片 5

大家获得的是键值小小的的极其对象.

运用一次索引,大家必须要得到一条数据;
要是大家要求得到全数title属性值为寻梦环游记的对象,大家得以使用游标.

键范围

游标也足以担当一个键,也正是透过键来设定游标查找的界定;
代码如下:

<!DOCTYPE html>
<html lang=”en”>
<head>
<meta charset=”UTF-8″>
<title>WebStorage DEMO</title>
</head>
<body>
<div class=”networkStatus”>
<button class=”clear”>清空数据</button>
<button class=”add”>加多数量</button>
<button class=”query”>查询数据</button>
<button class=”delete”>删除数据</button>
<button class=”cursor”>使用游标查询</button>
<button class=”keyRange”>使用keyrange查询</button>
<button class=”index”>使用index</button>
</div>

<script>
let network = document.querySelector(‘.networkStatus’),
addBtn = document.querySelector(‘.add’),
queryBtn = document.querySelector(‘.query’),
deleteBtn = document.querySelector(‘.delete’),
cursorBtn = document.querySelector(‘.cursor’),
clearBtn = document.querySelector(‘.clear’),
keyRange = document.querySelector(‘.keyRange’),
indexBtn = document.querySelector(‘.index’)
;

// 推断网路是不是在线
// if (navigator.onLine) {
// network.innerText = “网络在线”;
// } else {
// network.innerText = “网络掉线”;
// }

// // 监察和控制网络状态的轩然大波:online 和 offline, 那多少个事件在window对象上
// window.addEventListener(‘online’, () => {
// network.innerText = “网络在线”;
// });

// window.addEventListener(‘offline’, () => {
// network.innerText = “互联网掉线”;
// });

//——–cookie的使用—————
let CookieUtil = {
get: (name) => {
let cookieName = encodeURIComponent(name) + “=”,
cookieStart = document.cookie.indexOf(cookieName),
cookieValue = null;

  if (cookieStart > -1) {
    let cookieEnd = document.cookie.indexOf(';', cookieStart);
    if (cookieEnd === -1) {
      cookieEnd = document.cookie.length;
    }
    cookieValue = decodeURIComponent(document.cookie.substring(cookieStart + cookieName.length, cookieEnd));
  }

  return cookieValue;
},
set: function (name, value, expires, path, domain, secure) {
  let cookieText = encodeURIComponent(name) + '=' +
                   encodeURIComponent(value);

  if (expires instanceof Date) {
    cookieText += '; expires=' + expires.toGMTString();
  }

  if (path) {
    cookieText += '; path=' + path;
  }

  if (domain) {
    cookieText += '; domain=' + domain;
  }

  if (secure) {
    cookieText += '; secure';
  }

  document.cookie = cookieText;
},

// 删除cookie, 并没有直接的删除cookie的方法,这里通过重新设置cookie名称,来对cookie进行替换
// 同时 将过期时间expires设置为过去的时间,
unset: function(name, path, domain, secure) {
  this.set(name, '', new Date(0), path, domain, secure);
}

}

CookieUtil.set(‘name’, ‘hexon’);
CookieUtil.set(‘book’, ‘Profession Javascript’);

// 读取cookie的值
// console.log(CookieUtil.get(‘name’));
// console.log(CookieUtil.get(‘book’));

// 删除cookie
CookieUtil.unset(‘name’);
CookieUtil.unset(‘book’);

// 设置cookie, 包含它的渠道、域、失效日期
CookieUtil.set(‘name’, ‘Hexon’, ‘books/projs/’,
‘www.wrox.com’, new
Date(‘January 1, 2017’));

// 删除刚刚安装的cookie
CookieUtil.unset(‘name’, ‘books/projs/’,
‘www.www.wrox.com’);

// 设置安全的cookie
CookieUtil.unset(‘name’, ‘hexon’, null, null, null, null, true)

// — IndexedDB 数据库的施用
var request = window.indexedDB.open(‘dbName’, 2)
var db;
const dbName = ‘the_name’;
// 创立三个数目
const customerData = [
{ ssn: ‘444-44-4444’, name: ‘AAA’, age: 35, email:
‘AAA@company.com’},
{ ssn: ‘666-66-6666’, name: ‘CCC’, age: 35, email:
‘CCC@company.com’},
{ ssn: ‘777-77-7777’, name: ‘DDD’, age: 32, email:
‘DDD@home.org’},
{ ssn: ‘555-55-5555’, name: ‘BBB’, age: 32, email:
‘BBB@home.org’},

];

window.indexedDB = window.indexedDB || window.msIndexedDB ||
window.mozIndexedDB || window.webkitIndexedDB;
window.IDBTransaction = window.IDBTransaction ||
window.webkitIDBTransaction || window.msIDBTransaction || {READ_WRITE:
“readwrite”};
window.IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange ||
window.msIDBKeyRange;
window.IDBCursor = window.IDBCursor || window.webkitIDBTransaction;

if (!window.indexedDB) {
window.alert(“Your browser doesn’t support a stable version of
IndexedDB.”)
}

// 3
是成立的数据库版本,假若名字为MyTestDatabase的数据库不设有,就能够成立该数据库,然后
onupgradeneeded 事件会被触发;
// 假诺数据库存在,可是对版本进级了,也会触发onupgradeneeded事件,
// 注意:版本号是一个 unsigned long long
类型的值,由此不要接纳float,不然会将其退换为其最左近的卡尺头

// 生成管理程序
request.onerror = function (event) {
// do Something
alert(‘Database error: ‘ + event.target.errorCode);
};

request.onsuccess = function (event) {
// do Something
console.log(‘成立数据库成功’);
db = event.target.result; // 创立成功后,e.target.result
中蕴藏的是IDBDatabase对象的实例
}

// 当成立四个新的多寡库 只怕 更新已存在数据库的版本,
onupgradeneeded事件将会被触发,新的目的存款和储蓄在event.target.result中。
//
在该处理程序中,数据库已经持有先前版本的指标存储,由此没有必要再一次创建这一个指标存款和储蓄,只必要创建任何我们须求的目的存款和储蓄,也许
//
从从前版本中删除不在供给的指标存款和储蓄。假若供给转移当前指标存款和储蓄,则必得先删除旧的指标存款和储蓄,然后在采纳新的选项创设。
// 删除旧的靶子存款和储蓄,在其上的新闻都会被删去;
//
注意:该事件是天下无双一个可以预知对数据库进行操作的地点,在该事件之中,你对指标存款和储蓄进行删减、改革或移除索引
request.onupgradeneeded = function(event) {
console.log(‘onupgradeneeded’);
var db = event.target.result;

// 创建一个   对象存储空间,名为customers
var objectStore = db.createObjectStore('customers', {keyPath: 'ssn'});
// 对于某些数据,可以为一个对象存储空间指定多个键。比如,若要通过用户ID 和用户名 两种方式来保存用户资料,就需要通过两个键来存取记录
// 因此可以使用createIndex,名字是有可能重复的,所以其unique 设置为 false ;第一个name是索引的名字,该名字是索引的名字,第二个name是索引的属性的名字,该名字要与对象中的属性相同
objectStore.createIndex('name', 'name', { unique: false});

// // 创建一个email的索引,该email是独特的,所以 unique 设置为 true
objectStore.createIndex('email', 'email', { unique: true});

}

function save(data) {
///
对于数据库的对象存款和储蓄空间中多少的读取或涂改数据,都要透过事物来公司具备操作
// 最简便的创办事物的法子是:var transaction = db.transaction();
let transaction = db.transaction(‘customers’, ‘readwrite’); //
创立二个工作,并定义该事情的操作为 “readwrite” ,并回到其索引
let store = transaction.objectStore(‘customers’); //
获得索引后,使用objectStore()方法并传播存款和储蓄空间的名称,就足以访问特定的储存空间

for (var i in customerData) {
  let req = store.put(customerData[i]);   // 往一个存储空间中添加数据
}

transaction.oncomplete = function(event) {
  console.log(event.target);
  alert('存储数据完成');
};

transaction.onsuccess = function(event ) {
  console.log('onsuccess 事件');
}

}

function clear() {
// body…
let transaction = db.transaction(‘customers’, ‘readwrite’);
let store = transaction.objectStore(‘customers’).clear();
store.onerror = function(event) {
console.log(‘清空数据退步’);
}
store.onsuccess = function(event) {
console.log(‘清空数据成功’);
}
}

// 使用事务 直接通过已知的键索引 单个对象 (只好索引单个对象卡塔 尔(英语:State of Qatar)
function getData() {
let transaction = db.transaction(‘customers’, ‘readwrite’); //
创制多少个东西, 并定义该事情的操作为 “readonly”
let store = transaction.objectStore(‘customers’).get(‘444-44-4444’); //
使用get() 能够赢得值

store.onerror = function (event) {
  alert('did not get the object');
}

store.onsuccess = function (event) {
  var result = event.target.result;
  console.log(result);
  alert('获取数据完成! 年龄是: ' + result.age);
}

}

function deleteData() {
let transaction = db.transaction(‘customers’, ‘readwrite’);
let store = transaction.objectStore(‘customers’);
store.delete(‘444-44-4444’);
alert(‘s删除数据产生’);
}

// 在事行业内部创立游标查询 能够索引 多少个目的(注意: 是几个对象卡塔 尔(英语:State of Qatar)
// 游标不提前手提式有线电话机结果
function cursorQuery() {
let transaction = db.transaction(‘customers’, ‘readwrite’),
store = transaction.objectStore(‘customers’),
request = store.openCursor(null) ; // 这里创办游标

request.onsuccess = function (event) {

  // event.target.result 中保存的是在存储空间中查询到的对象
  // event.target.result 中有几个属性值,可以了解到查询到的对象中的细节,
  // key: 当前访问的对象的键
  // value:当前访问的实际对象
  // primaryKey: 游标使用的键
  // direction:数值,表示游标移动的方向

  let cursor = event.target.result;
  let value, updateRequest, deleteRequest;
  if (cursor) {
  //   if (cursor.key === '555-55-5555') {
  //     value = cursor.value;   // 获取到实际的访问对象
  //     value.name = 'hexon';   // 修改对象的name属性

  //     updateRequest = cursor.update(value);      // 调用update()方法可以用指定的对象,更新对象的value
  //     updateRequest.onsuccess = function() {
  //       // 处理成功
  //     }
  //     updateRequest.onerror = function() {
  //       // 处理失败
  //     }


  //     // 使用游标删除当前项
  //     // deleteRequest = cursor.delete();
  //     // deleteRequest.onsuccess = function() {
  //     //   // 删除成功处理
  //     // }
  //     // deleteRequest.onerror = function() {
  //     //   // 删除失败处理
  //     // }


  //   }
  //   console.log(event.target.result);
  // }
  console.log(cursor.value);
  cursor.continue();      // 移动到下一项,
  }
  request.onerror = function(event) {
    console.log('游标查询创建失败')
  }
}

}

// 使用keyrange查询
function keyRangeQuery() {
let transaction = db.transaction(‘customers’, ‘readwrite’)
let store = transaction.objectStore(‘customers’);
// 使用bound()方法 定义键范围
let range = IDBKeyRange.bound(‘555-55-5555’, ‘777-77-7777’, true,
false);
// 将键传入游标创造
let request = store.openCursor(range);

request.onsuccess = function(event) {
  let cursor = event.target.result;
  if (cursor) {
    console.log('游标查询到的值' + JSON.stringify(cursor.value));
    cursor.continue()     // 移动到下一项
  }

}

request.onerror = function(event) {
  console.log("使用游标 + keyrange 查询失败")
}

}

// 使用索引
function useIndex() {
let store = db.transaction(‘customers’).objectStore(‘customers’),
index = store.index(‘name’);
request = index.openCursor();
request.onsuccess = function (event) {
let cursor = event.target.result;
if (cursor) {
console.log(cursor);
cursor.continue();
}
}
}

addBtn.addEventListener(‘click’, function(e) {
save();
}, false);

deleteBtn.addEventListener(‘click’, function(e) {
deleteData();
}, false);

queryBtn.addEventListener(‘click’, function(e) {
getData();
}, false);

cursorBtn.addEventListener(‘click’, function(e) {
cursorQuery();
}, false);

clearBtn.addEventListener(‘click’, function(e) {
clear();
}, false);

keyRange.addEventListener(‘click’, function(e) {
keyRangeQuery();
}),

indexBtn.addEventListener(‘click’, function(e) {
useIndex();
})

</script>

</body>
</html>

六、使用游标

赢得三个方可操作游标的央求对象有八个章程:

  • openCursor(keyRange, direction)
  • openKeyCursor(keyRange, direction)
    那八个法子采取的参数同样, 七个参数都以可选的:
    第二个参数是限量值得范围,第三个参数是点名游标方向

游标的选取有以下几处:

  • 在指标存款和储蓄空间上行使: var cursor = objectStore.openCursor()
  • 在目录对象上利用: var cursor = index.openCursor()

在对象存款和储蓄空间上接受游标

采取游标平淡无奇的风度翩翩种形式是获得对象存款和储蓄空间上的保有数据.

var list = []; var objectStore =
db.transaction(‘movies’).objectStore(‘movies’);
objectStore.openCursor().onsuccess = function(event) { var cursor =
event.target.result; if (cursor) { console.log(‘cursor:’, cursor);
list.push(cursor.value); cursor.continue(); } else { console.log(‘Get
all data:’, list); } };

1
2
3
4
5
6
7
8
9
10
11
12
var list = [];
var objectStore = db.transaction(‘movies’).objectStore(‘movies’);
objectStore.openCursor().onsuccess = function(event) {
    var cursor = event.target.result;
    if (cursor) {
        console.log(‘cursor:’, cursor);
        list.push(cursor.value);
        cursor.continue();
    } else {
        console.log(‘Get all data:’, list);
    }
};

图片 6

行使游标时,须要在成功回调里获得result对象,剖断是还是不是取完了数量:若数据已取完,resultundefined;
若未取完,则result是个IDBCursorWithValue对象,需调用continue()办法继续取多少。
也足以依附自身必要, 对数码实行过滤。

indexedDB2规范中,在目标存款和储蓄空间对象上归入了二个getAll()办法,能够得到具备目标:

objectStore.getAll().onsuccess = function(event) {
console.log(‘result:’, event.target.result); };

1
2
3
objectStore.getAll().onsuccess = function(event) {
    console.log(‘result:’, event.target.result);
};

在目录上行使游标

跟着本文上述使用索引的例子,在目录title上使用openCursor()主意时,若不传参数,则会遍历全体数据,在功成名就回调中的到的result指标有以下属性:

  • key 数据库中那条对象的title属性值
  • primaryKey 数据库中那条对象的alt
  • value 数据库中那条对象
  • direction openCursor()方法传入的第一个对象,默许值为next
  • source IDBIndex对象 举个例子如下:
var index = db .transaction('movies')
.objectStore('movies').index('title'); index.openCursor().onsuccess
= function(event) { var cursor = event.target.result; if (cursor) {
console.log('cursor:', cursor); cursor.continue(); } };

<table>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<tbody>
<tr class="odd">
<td><div class="crayon-nums-content" style="font-size: 13px !important; line-height: 15px !important;">
<div class="crayon-num" data-line="crayon-5b8f37afae763506229096-1">
1
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f37afae763506229096-2">
2
</div>
<div class="crayon-num" data-line="crayon-5b8f37afae763506229096-3">
3
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f37afae763506229096-4">
4
</div>
<div class="crayon-num" data-line="crayon-5b8f37afae763506229096-5">
5
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f37afae763506229096-6">
6
</div>
<div class="crayon-num" data-line="crayon-5b8f37afae763506229096-7">
7
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f37afae763506229096-8">
8
</div>
<div class="crayon-num" data-line="crayon-5b8f37afae763506229096-9">
9
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f37afae763506229096-10">
10
</div>
</div></td>
<td><div class="crayon-pre" style="font-size: 13px !important; line-height: 15px !important; -moz-tab-size:4; -o-tab-size:4; -webkit-tab-size:4; tab-size:4;">
<div id="crayon-5b8f37afae763506229096-1" class="crayon-line">
var index = db
</div>
<div id="crayon-5b8f37afae763506229096-2" class="crayon-line crayon-striped-line">
.transaction('movies')
</div>
<div id="crayon-5b8f37afae763506229096-3" class="crayon-line">
.objectStore('movies').index('title');
</div>
<div id="crayon-5b8f37afae763506229096-4" class="crayon-line crayon-striped-line">
index.openCursor().onsuccess = function(event) {
</div>
<div id="crayon-5b8f37afae763506229096-5" class="crayon-line">
  var cursor = event.target.result;
</div>
<div id="crayon-5b8f37afae763506229096-6" class="crayon-line crayon-striped-line">
  if (cursor) {
</div>
<div id="crayon-5b8f37afae763506229096-7" class="crayon-line">
      console.log('cursor:', cursor);
</div>
<div id="crayon-5b8f37afae763506229096-8" class="crayon-line crayon-striped-line">
      cursor.continue();
</div>
<div id="crayon-5b8f37afae763506229096-9" class="crayon-line">
  }
</div>
<div id="crayon-5b8f37afae763506229096-10" class="crayon-line crayon-striped-line">
};
</div>
</div></td>
</tr>
</tbody>
</table>


[![](http://jbcdn2.b0.upaiyun.com/2017/12/5451a2dedd05d9226415141022934c72.png)](http://jbcdn2.b0.upaiyun.com/2017/12/5451a2dedd05d9226415141022934c72.png)

在索引title上使用openKeyCursor()办法,若不传参数,相通也会遍历全数数据,result对象属性如下:

  • key 数据库中那条对象的title属性值
  • primaryKey 数据库中那条对象的alt
  • direction openCursor()方法传入的第一个对象,暗许值为next
  • source altBIndex对象

openCursor()艺术比较,获得的数目少一个value品质,是从未艺术获得存款和储蓄对象的其他部分

前边提起,大家要基于目录title收获具备title属性值为寻梦环游记的靶子,要接收游标,而又不想遍历全体数据,这个时候将在接收openCursor()的第二个参数:
keyRange

keyRange是节制游标遍历的数目范围,通过IDBKeyRange的片段主意设置该值:

var singleKeyRange = IDBKeyRange.only(“寻梦环游记”), list = []; var
index = db .transaction(‘movies’) .objectStore(‘movies’).index(‘title’);
index.openCursor(singleKeyRange).onsuccess = function(event) { var
cursor = event.target.result; if (cursor) { console.log(‘cursor.value:’,
cursor.value); list.push(cursor.value); cursor.continue(); } else {
console.log(‘list:’, list); } };

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var singleKeyRange = IDBKeyRange.only("寻梦环游记"), list = [];
var index = db
.transaction(‘movies’)
.objectStore(‘movies’).index(‘title’);
index.openCursor(singleKeyRange).onsuccess = function(event) {
var cursor = event.target.result;
if (cursor) {
console.log(‘cursor.value:’, cursor.value);
list.push(cursor.value);
cursor.continue();
} else {
    console.log(‘list:’, list);
}
};

图片 7

IDBKeyRange此外部分艺术:

// 相配全数在 “Bill” 前面包车型大巴, 包蕴 “Bill” var lowerBoundKeyRange =
IDBKeyRange.lowerBound(“Bill”); // 相配全部在 “比尔” 前边的,
不过无需满含 “Bill” var lowerBoundOpenKeyRange =
IDBKeyRange.lowerBound(“Bill”, true); // 匹配全体在’Donna’前边的,
可是不满含”Donna” var upperBoundOpenKeyRange =
IDBKeyRange.upperBound(“Donna”, true); // 相称全数在”Bill” 和 “堂娜”
之间的, 不过不包含 “Donna” var boundKeyRange = IDBKeyRange.bound(“Bill”,
“Donna”, false, true);

1
2
3
4
5
6
7
8
9
10
11
// 匹配所有在 "Bill" 前面的, 包括 "Bill"
var lowerBoundKeyRange = IDBKeyRange.lowerBound("Bill");
 
// 匹配所有在 “Bill” 前面的, 但是不需要包括 "Bill"
var lowerBoundOpenKeyRange = IDBKeyRange.lowerBound("Bill", true);
 
// 匹配所有在’Donna’后面的, 但是不包括"Donna"
var upperBoundOpenKeyRange = IDBKeyRange.upperBound("Donna", true);
 
// 匹配所有在"Bill" 和 "Donna" 之间的, 但是不包括 "Donna"
var boundKeyRange = IDBKeyRange.bound("Bill", "Donna", false, true);

越来越多请参照他事他说加以调查
MDN|IDBKeyRange

游标私下认可遍历方向是按主键从小到大,一时候大家倒序遍历,当时得以给openCursor()方法传递第三个参数:
direction: next|nextunique|prev|prevunique

var singleKeyRange = IDBKeyRange.only(“寻梦环游记”), list = []; var
index = db .transaction(‘movies’) .objectStore(‘movies’).index(‘title’);
index.openCursor(singleKeyRange, ‘prev’).onsuccess = function(event) {
var cursor = event.target.result; if (cursor) {
console.log(‘cursor.value:’, cursor.value); list.push(cursor.value);
cursor.continue(); } else { console.log(‘list:’, list); } };

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var singleKeyRange = IDBKeyRange.only("寻梦环游记"), list = [];
var index = db
.transaction(‘movies’)
.objectStore(‘movies’).index(‘title’);
index.openCursor(singleKeyRange, ‘prev’).onsuccess = function(event) {
var cursor = event.target.result;
if (cursor) {
console.log(‘cursor.value:’, cursor.value);
list.push(cursor.value);
cursor.continue();
} else {
    console.log(‘list:’, list);
}
};

传了prev的结果是按倒序遍历的.

因为 “name” 索引不是独步一时的,那就有非常的大希望存在具备相符 name 的多条记下。
要小心的是这种情状不或许产生在目的存款和储蓄空间上,因为键必得恒久是并世无两的。
假如您想要在游标在目录迭代进度中过滤出双重的,你能够传递
nextunique(或prevunique, 尽管你正在向后查找)作为方向参数。 当
nextunique 或是 prevunique
被利用时,被重回的十分总是键最小的笔录。

var singleKeyRange = IDBKeyRange.only(“寻梦环游记”), list = []; var
index = db .transaction(‘movies’) .objectStore(‘movies’).index(‘title’);
index.openCursor(singleKeyRange, ‘prevunique’).onsuccess =
function(event) { var cursor = event.target.result; if (cursor) {
console.log(‘cursor.value:’, cursor.value); list.push(cursor.value);
cursor.continue(); } else { console.log(‘list:’, list); } };

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var singleKeyRange = IDBKeyRange.only("寻梦环游记"), list = [];
var index = db
.transaction(‘movies’)
.objectStore(‘movies’).index(‘title’);
index.openCursor(singleKeyRange, ‘prevunique’).onsuccess = function(event) {
var cursor = event.target.result;
if (cursor) {
console.log(‘cursor.value:’, cursor.value);
list.push(cursor.value);
cursor.continue();
} else {
    console.log(‘list:’, list);
}
};

图片 8

七、关闭和删除数据库

  • 关闭数据库只必要在数据库对象db上调用close()办法就能够
db.close();

<table>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<tbody>
<tr class="odd">
<td><div class="crayon-nums-content" style="font-size: 13px !important; line-height: 15px !important;">
<div class="crayon-num" data-line="crayon-5b8f37afae779476637224-1">
1
</div>
</div></td>
<td><div class="crayon-pre" style="font-size: 13px !important; line-height: 15px !important; -moz-tab-size:4; -o-tab-size:4; -webkit-tab-size:4; tab-size:4;">
<div id="crayon-5b8f37afae779476637224-1" class="crayon-line">
db.close();
</div>
</div></td>
</tr>
</tbody>
</table>


关闭数据库后,`db`对象仍然保存着该数据库的相关信息,只是无法再开启事务(调用开启事务方法会报错,提示数据库连接已断开):

图片 9

  • 删去数据库则须求动用indexedDB.deleteDatabase(dbName)方法
JavaScript

window.indexedDB.deleteDatabase(dbName);

<table>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<tbody>
<tr class="odd">
<td><div class="crayon-nums-content" style="font-size: 13px !important; line-height: 15px !important;">
<div class="crayon-num" data-line="crayon-5b8f37afae77e452573671-1">
1
</div>
</div></td>
<td><div class="crayon-pre" style="font-size: 13px !important; line-height: 15px !important; -moz-tab-size:4; -o-tab-size:4; -webkit-tab-size:4; tab-size:4;">
<div id="crayon-5b8f37afae77e452573671-1" class="crayon-line">
window.indexedDB.deleteDatabase(dbName);
</div>
</div></td>
</tr>
</tbody>
</table>

八、indexedDB的局限性

以下景况不相符接收IndexedDB

  • 满世界各样语言混合存款和储蓄。国际化支持倒霉。须要自身管理。
  • 和服务器端数据库同步。你得温馨写同步代码。
  • 全文字笔迹查证索。

留意,在以下意况下,数据库只怕被免去:

  • 客户央浼消亡数据。
  • 浏览器处于隐衷形式。最后退出浏览器的时候,数据会被撤消。
  • 硬盘等存储设备的体积到限。
  • 不得法的
  • 不完全的更改.

总结

  1. 使用indexedDB.open(dbName, version)开发一个数据库连接
  2. 使用indexedDB.deleteDatabase(dbName)去除叁个数据库
  3. 在数据库对象db上使用createObjectStore(storeName, config)创立对象存款和储蓄空间
  4. 在对象存款和储蓄空间objectStore上使用createIndex(indexName, keyName, config)创建索引
  5. 对数据库的操作都亟待经过事务完成:
    var transction = db.transaction([storeName], mode)
  6. 数据库的增加和删除改查均通过objectStore指标完毕,var objectStore = transaction.objectStore(storeName)
  7. 对数据库数据操作有: add()get()delete()put等方法
  8. 寻觅数据可以行使索引: objectStore.index(indexName)
  9. 遍历和过滤数据足以应用游标: openCursor(keyRange, direction)

参照链接

  • IndexedDB的基本概念-MDN
  • 使用
    IndexedDB-MDN
  • IndexedDB
    API接口-MDN
  • Indexed Database API 2.0 – w3c

    1 赞 2 收藏 1
    评论

图片 10

发表评论