图片 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, VECR-VSION); 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]
      (个中的key帕特h属性值,标记对象的该属性值唯生机勃勃)
  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事件的效能:当张开了二个数据库之后,须求开荒三个名叫:目的存款和储蓄空间
的钱物(能够驾驭为多少正是贮存在这里个空间里面,三个数据库能够创制三个对象存款和储蓄空间卡塔 尔(英语:State of Qatar),而
对象存款和储蓄空间 只能在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删除数据产生’);
}

// 在事情内创建游标查询 能够索引 多少个对象(注意: 是五个对象卡塔尔国
// 游标不提前手提式有线话机结果
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()方法传入的第1个对象,暗许值为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”
之间的, 可是不包含 “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

发表评论

电子邮件地址不会被公开。 必填项已用*标注