菜单

IndexedDB数据库

2019年4月5日 - Html/Html5

使用IndexedDB

明日,你早就有空子熟识了壹些的完全概念,下一步是发轫兑现基于IndexedDB的应用程序。第3个步骤必要统1IndexedDB在不一致浏览器的贯彻。您能够很不难地抬高种种厂商性情的挑选的检讨,同时在window对象上把它们设置为官方对象相同的称谓。上面包车型大巴清单呈现了window.indexedDB,window.IDBTransaction,window.IDBKeyRange的结尾结果是何等都被更新,它们棉被服装置为对应的浏览器的特定达成。

JavaScript

window.indexedDB = window.indexedDB || window.mozIndexedDB ||
window.webkitIndexedDB || window.msIndexedDB; window.IDBTransaction =
window.IDBTransaction || window.webkitIDBTransaction ||
window.msIDBTransaction; window.IDBKeyRange = window.IDBKeyRange ||
window.webkitIDBKeyRange || window.msIDBKeyRange;

1
2
3
4
5
6
7
8
9
10
window.indexedDB = window.indexedDB ||
                   window.mozIndexedDB ||
                   window.webkitIndexedDB ||
                   window.msIndexedDB;
window.IDBTransaction = window.IDBTransaction ||
                   window.webkitIDBTransaction ||
                   window.msIDBTransaction;
window.IDBKeyRange = window.IDBKeyRange ||
                   window.webkitIDBKeyRange ||
                   window.msIDBKeyRange;

最近,各种数据库相关的大局对象具备正确的版本,应用程序能够准备选用IndexedDB初叶工作。

行使方式

指标仓库

object
store是IndexedDB数据库的根底。若是您接纳过关全面据库,常常能够将object
store等价于贰个数量库表。Object
stores蕴涵一个或四个目录,在store中服从壹对键/值操作,那提供1种高效稳定数据的办法。

当你安插1个object
store,你不能够不为store选拔三个键。键在store中能够以“in-line”或“out-of-line”的办法存在。in-line键通过在数额对象上引用path来维系它在object
store的唯1性。为了验证那或多或少,想想五个归纳电子邮件地址属性Person对象。您能够配备你的store使用in-line键emailAddress,它能担保store(持久化对象中的数据)的唯一性。其余,out-of-line键通过单独于数据的值识别唯壹性。在那种景色下,你能够把out-of-line键比作二个平头值,它(整数值)在关周到据库中担任记录的主键。

图壹出示了职分数据保存在任务的object
store,它使用in-line键。在那么些案例中,键对应于对象的ID值。

政工和查询操作数据

最简易的创导工作的方式是:
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后,大家能够动用如下方法对数码开始展览操作:

注意:通过oncomplete事件指标,访问不到get()请求再次回到的其余数据,必须在响应请求的onsuccess事件处理程序中才能访问到数码

铺设基础

其1例子从贯彻如此贰个模块初步,它担负从数据库读取数据,插入新的对象,更新现有对象,删除单个对象和提供在三个object
store删除全体目的的选项。这一个例子完成的代码是通用的数码访问代码,您能够在任何object
store上选取。

以此模块是透过多个立马实施函数表明式(IIFE)实现,它使用对象字面量来提供协会。下边的代码是模块的摘要,表明了它的主导组织。

JavaScript

(function (window) { ‘use strict’; var db = { /* implementation here
*/ }; window.app = window.app || {}; window.app.db = db; }(window));

1
2
3
4
5
6
7
8
(function (window) {
    ‘use strict’;
    var db = {
        /* implementation here */
    };
    window.app = window.app || {};
    window.app.db = db;
}(window));

用如此的构造,可以使那些应用程序的具备逻辑封装在二个名称为app的单对象上。别的,数据库相关的代码在三个名称叫db的app子对象上。

以此模块的代码应用IIFE,通过传递window对象来担保模块的适宜范围。使用use
strict确定保证那么些函数的代码函数是遵从(javascript严酷格局)严刻编写翻译规则。db对象作为与数据库交互的具备函数的机要容器。最后,window对象检查app的实例是或不是留存,假如存在,模块使用当前实例,假设不存在,则创制一个新目标。壹旦app对象成功重回或创办,db对象附加到app对象。

正文的别的部分将代码添加到db对象内(在implementation
here会
评价),为应用程序提供特定于数据库的逻辑。由此,如您所见本文后边的局地中定义的函数,想想父db对象活动,但全数别的职能皆以db对象的分子。完整的数据库模块列表见清单②。

indexDB.open()办法的法则

分为二种情景:
一. 流传的数据库不设有
当传入的数据库不存在时,该方法就会创设三个名叫name的数据库,并打开它,此时,会先触发upgradeneeded事件;调用该函数会再次来到四个IDBRequest对象,能够在该对象上添加onsuccess事件onerror事件
注意:当打开三个不存在的数据库时会触发upgradeneeded事件,那是触发该事件的1种途径,为啥会触发该事件吧?该事件有哪些效益?留个问号在此刻,等会解答。

二. 传播的数据仓库储存在
此地分为两种状态:

利用概述

在本教程中,您将学习怎么样创制四个利用IndexedDB存款和储蓄数据的模块化JavaScript应用程序。为了精通应用程序是何等做事的,参考图4,它讲述了职务应用程序处于空白状态。从此处您能够为列表添加新职分。图伍显得了录入了多少个职分到系统的画面。图陆突显怎么删除二个职务,图7显示了正在编写制定任务时的应用程序。

图片 1

图4:空白的任务应用程序

图片 2

图伍:职责列表

图片 3

图陆:删除职分

图片 4

图七:编辑职务
当今你熟识的应用程序的功能,下一步是初阶为网址铺设基础。

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});
}

浏览器帮忙

兴许在付出Web应用程序最要害的难题是:“浏览器是或不是援救笔者想要做的?“就算浏览器对IndexedDB的扶助在三番陆遍增加,选拔率并不是大家所期待的那样普遍。图3彰显了caniuse.com网站的告诉,补助IndexedDB的为6六%多一丝丝。最新版本的银狐,Chrome,Opera,Safar,iOS
Safari,和Android完全帮忙IndexedDB,Internet
Explorer和BlackBerry部分帮助。即便这些列表的拥护者是激动的,但它从未告知全体故事。

图片 5

图3:浏览器对IndexedDB的支撑,来自caniuse.com

只有可怜新本子的Safari和iOS Safari
补助IndexedDB。据caniuse.com显示,那只占差不多0.01%的全球浏览器接纳。IndexedDB不是三个您觉得能够理所当然获得协助的现代Web
API,可是你将高速会这么认为。

老是数据库

要选拔它必须先打开,通过 indexDB.open(name, version)办法打开3个数据库

依照事务

不一样于1些观念的关周密据库的达成,每四个对数据库操作是在二个作业的内外文中执行的。事务限制三回影响3个或多少个object
stores,你通过传播三个object store名字的数组到成立工作限制的函数来定义。

制造工作的第1个参数是业务格局。当呼吁1个事务时,必须控制是奉公守法只读照旧读写情势请求访问。事务是财富密集型的,所以假使你不需求更改data
store中的数据,你只须要以只读情势对object stores集合举办呼吁访问。

清单二示范了如何运用格外的情势开创一个作业,并在这片作品的 Implementing
Database-Specific Code
 部分开始展览了详尽座谈。

存款和储蓄数据

积存数据有三种办法: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对象存款和储蓄空间中

地点代码中提到了
[事务],那里先记住:举凡涉及到对数据库的读写删除操作,都供给通过
[事务] 来完成

有关笔者:cucr

图片 6

知乎新浪:@hop_ping
个人主页
·
作者的文章
·
17

图片 7

选择游标查询数据

应用工作能够间接通过
已知的键检索单个对象。而在急需摸索三个目标时,则须求在工作内创设游标。

游标并不会提前收集结果,游标先指向结果中的第2项,在收到查找下壹项的通令时,才会指向下一项

如下:

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()措施删除当前项

张冠李戴冒泡

当然,有时候,请求恐怕不会按预期完毕。IndexedDB
API通过荒谬冒泡效果来赞助跟踪和治本漏洞百出。如若一个一定的央浼碰到错误,你能够品尝在呼吁对象上处理错误,可能您能够允许错误通过调用栈冒泡向上传递。那些冒泡性情,使得你不须要为每一种请求完结特定错误处理操作,而是能够选用只在八个越来越高级别上添加错误处理,它给您3个机遇,保持您的错误处理代码简洁。本文中贯彻的例子,是在二个高级别处理错误,以便更细粒度操作发生的任何错误冒泡到通用的错误处理逻辑。

键范围

游标也足以承受二个键,也正是经过键来设定游标查找的限量;
代码如下:

<!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’;
// 成立2个多少
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中。
//
在该处理程序中,数据库已经具有先前版本的靶子存款和储蓄,由此不用再一次创建那一个目的存款和储蓄,只须要创立任何大家须要的目的存款和储蓄,恐怕
//
从原先版本中除去不在必要的对象存款和储蓄。要是须要改变当前目的存款和储蓄,则必须先删除旧的目的存款和储蓄,然后在动用新的选项创立。
// 删除旧的靶子存款和储蓄,在其上的新闻都会被去除;
//
注意:该事件是绝无仅有3个力所能及对数据库进行操作的地方,在该事件之中,你对目的存款和储蓄实行删减、修改或移除索引
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(‘清空数据成功’);
}
}

// 使用事务 间接通过已知的键索引 单个对象 (只可以索引单个对象)
function getData() {
let transaction = db.transaction(‘customers’, ‘readwrite’); //
成立多个事物, 并定义该事情的操作为 “readonly”
let store = transaction.objectStore(‘customers’).get(’44四-4四-444四’); //
使用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>

前者的数据库:IndexedDB入门

2014/12/27 · 未分类 · IndexedDB

本文由 伯乐在线
cucr
翻译,黄利民
校稿。未经许可,禁止转发!
英文出处:www.codemag.com。欢迎参与翻译组

应用程序必要多少。对多数Web应用程序来说,数据在服务器端协会和管理,客户端通过网络请求获取。随着浏览器变得尤其有能力,因而可选择在浏览器存款和储蓄和控制应用程序数据。

本文向你介绍名称为IndexedDB的浏览器端文书档案数据库。使用lndexedDB,你能够经过惯于在劳务器端数据库大概同一的秘籍开创、读取、更新和删除多量的笔录。请使用本文中可工作的代码版本去体会,完整的源代码能够经过GitHub库找到。

读到本课程的末梢时,你将熟练IndexedDB的基本概念以及怎么着落到实处二个利用IndexedDB执行总体的CRUD操作的模块化JavaScript应用程序。让我们略微亲近IndexedDB并初叶吧。

什么是IndexedDB

壹般的话,有三种差别档次的数据库:关系型和文书档案型(也叫做NoSQL或对象)。关全面据库如SQL
Server,MySQL,Oracle的数目存款和储蓄在表中。文书档案数据库如MongoDB,CouchDB,Redis将数据集作为个人对象存款和储蓄。IndexedDB是二个文书档案数据库,它在一点壹滴内停放浏览器中的三个沙盒环境中(强制依照(浏览器)同源策略)。图一体现了IndexedDB的多寡,呈现了数据库的构造

图片 8

图一:开发者工具查看3个object
store

全方位的IndexedDB API请参见完整文书档案

介绍

IndexedDB正是三个数据库
其最大的天性是:
动用对象保存数据,而不是采纳表来保存数据,同时,它是异步的

另1种选拔

浏览器援救本地数据库并不是从IndexedDB才起来兑现,它是在WebSQL兑现之后的1种新措施。类似IndexedDB,WebSQL是二个客户端数据库,但它看成一个关周详据库的落到实处,使用结构化查询语言(SQL)与数据库通讯。WebSQL的野史充满了弯曲,但底线是一直不主流的浏览器厂商对WebSQL继续援救。

借使WebSQL实际上是三个丢弃的技艺,为何还要提它吗?有趣的是,WebSQL在浏览器里获得巩固的支撑。Chrome,
Safari, iOS Safari, and
Android 浏览器都辅助。别的,并不是那么些浏览器的前卫版本才提供支撑,许多那个最新最佳的浏览器在此以前的版本也足以帮衬。有趣的是,假使您为WebSQL添加协理来支撑IndexedDB,你突然发现,许多浏览器厂商和版本成为支撑浏览器内置数据库的某种化身。

故而,假使你的应用程序真正必要3个客户端数据库,你想要达到的最高级其余使用恐怕,当IndexedDB不可用时,或然你的应用程序大概看起来必要选用选择WebSQL来援助客户端数据架构。即便文书档案数据库和关周密据库管理数据有令人惊讶标出入,但假若你有科学的悬空,就能够运用本地数据库创设3个应用程序。

Implementing Database-Specific Code

对数据库的每一种操作关联着一个先决条件,即有2个打开的数据库。当数据库正在被打开时,通过检查数据库版本来判定数据库是或不是需求其它变动。下边包车型地铁代码突显了模块如何跟踪当前版本,object
store名、某成员(保存了假设数据库打开请求达成后的数据库当前实例)。

JavaScript

version: 1, objectStoreName: ‘tasks’, instance: {},

1
2
3
version: 1,
objectStoreName: ‘tasks’,
instance: {},

在那边,数据库打开请求发生时,模块请求版本一数据库。假若数据库不存在,可能版本小于1,upgrade
needed事件在开辟请求达成前触发。这么些模块棉被服装置为只利用二个object
store,所以名字直接定义在那里。最终,实例成员被成立,它用于保存壹旦打开请求实现后的数据库当前实例。

接下去的操作是贯彻upgrade
needed事件的事件处理程序。在此地,检查当前object
store的名字来判定请求的object store名是或不是留存,尽管不存在,创设object
store。

JavaScript

upgrade: function (e) { var _db = e.target.result, names =
_db.objectStoreNames, name = db.objectStoreName; if
(!names.contains(name)) { _db.createObjectStore( name, { keyPath: ‘id’,
autoIncrement: true }); } },

1
2
3
4
5
6
7
8
9
10
11
12
13
14
upgrade: function (e) {
    var
        _db = e.target.result,
        names = _db.objectStoreNames,
        name = db.objectStoreName;
    if (!names.contains(name)) {
        _db.createObjectStore(
            name,
            {
                keyPath: ‘id’,
                autoIncrement: true
            });
    }
},

在那么些事件处理程序里,通过事件参数e.target.result来访问数据库。当前的object
store名称的列表在_db.objectStoreName的字符串数组上。未来,即便object
store不存在,它是经过传递object
store名称和store的键的概念(自增,关联到数量的ID成员)来创设。

模块的下贰个成效是用来捕获错误,错误在模块不一样的呼吁成立时冒泡。

JavaScript

errorHandler: function (error) { window.alert(‘error: ‘ +
error.target.code); debugger; },

1
2
3
4
errorHandler: function (error) {
    window.alert(‘error: ‘ + error.target.code);
    debugger;
},

在此间,errorHandler在一个警告框突显别的错误。这一个函数是明知故犯保持简单,对开发自身,当您学习使用IndexedDB,您能够很简单地看到其余不当(当她们产生时)。当你准备在生养环境使用那么些模块,您须要在这些函数中贯彻部分错误处理代码来和你的应用程序的上下文打交道。

现今基础实现了,那一节的别的部分将演示怎么着兑现对数据库执行一定操作。第3个要求检查的函数是open函数。

JavaScript

open: function (callback) { var request = window.indexedDB.open(
db.objectStoreName, db.version); request.onerror = db.errorHandler;
request.onupgradeneeded = db.upgrade; request.onsuccess = function (e) {
db.instance = request.result; db.instance.onerror = db.errorHandler;
callback(); }; },

1
2
3
4
5
6
7
8
9
10
11
12
open: function (callback) {
    var request = window.indexedDB.open(
        db.objectStoreName, db.version);
    request.onerror = db.errorHandler;
    request.onupgradeneeded = db.upgrade;
    request.onsuccess = function (e) {
        db.instance = request.result;
        db.instance.onerror =
            db.errorHandler;
        callback();
    };
},

open函数试图打开数据库,然后实施回调函数,告知数据库成功打开药方可准备选用。通过访问window.indexedDB调用open函数来成立打开请求。那些函数接受你想打开的object
store的名目和你想行使的数据库版本号。

借使请求的实例可用,第一步要拓展的行事是安装错误处理程序和提高函数。记住,当数据库被打开时,假设脚本请求比浏览器里更加高版本的数据库(恐怕只要数据库不设有),升级函数运营。然则,假若请求的数据库版本相称当前数据库版本同时没有不当,success事件触发。

倘使全勤成功,打开数据库的实例能够从呼吁实例的result属性获得,那么些实例也缓存到模块的实例属性。然后,onerror事件设置到模块的errorHandler,作为以往其他请求的谬误捕捉处理程序。最终,回调被实践来报告调用者,数据库已经开辟并且正确地配备,能够运用了。

下一个要兑现的函数是helper函数,它回到所请求的object store。

JavaScript

getObjectStore: function (mode) { var txn, store; mode = mode ||
‘readonly’; txn = db.instance.transaction( [db.objectStoreName],
mode); store = txn.objectStore( db.objectStoreName); return store; },

1
2
3
4
5
6
7
8
9
getObjectStore: function (mode) {
    var txn, store;
    mode = mode || ‘readonly’;
    txn = db.instance.transaction(
        [db.objectStoreName], mode);
    store = txn.objectStore(
        db.objectStoreName);
    return store;
},

在那里,getObjectStore接受mode参数,允许你决定store是以只读照旧读写情势请求。对于这一个函数,私下认可mode是只读的。

每种针对object
store的操作都以在3个东西的前后文中执行的。事务请求接受八个object
store名字的数组。那个函数本次被布署为只行使3个object
store,可是如果你要求在业务中操作多少个object store,你供给传递四个object
store的名字到数组中。事务函数的第贰个参数是一个方式。

假如事情请求可用,您就足以由此传递要求的object
store名字来调用objectStore函数以博取object
store实例的访问权。那个模块的任何函数使用getObjectStore来得到object
store的访问权。

下三个贯彻的函数是save函数,执行插入或更新操作,它依照传入的数量是或不是有3个ID值。

JavaScript

save: function (data, callback) { db.open(function () { var store,
request, mode = ‘readwrite’; store = db.getObjectStore(mode), request =
data.id ? store.put(data) : store.add(data); request.onsuccess =
callback; }); },

1
2
3
4
5
6
7
8
9
10
11
12
save: function (data, callback) {
    db.open(function () {
        var store, request,
            mode = ‘readwrite’;
 
        store = db.getObjectStore(mode),
        request = data.id ?
            store.put(data) :
            store.add(data);
        request.onsuccess = callback;
    });
},

save函数的五个参数分别是亟需保留的数目对象实例和操作成功后必要实施的回调。读写格局用于将数据写入数据库,它被盛传到getObjectStore来获取object
store的七个可写实例。然后,检查数据对象的ID成员是或不是存在。如若存在ID值,数据必须立异,put函数被调用,它创立持久化请求。不然,倘使ID不设有,那是新数据,add请求重临。最终,不管put也许add
请求是或不是进行了,success事件处理程序必要设置在回调函数上,来报告调用脚本,一切进展顺遂。

下1节的代码在清单壹所示。getAll函数首先打开数据库和走访object
store,它为store和cursor(游标)分别设置值。为数据库游标设置游标变量允许迭代object
store中的数据。data变量设置为三个空数组,充当数据的器皿,它回到给调用代码。

在store访问数据时,游标遍历数据库中的每条记下,会触发onsuccess事件处理程序。当每条记下走访时,store的数码足以透过e.target.result事件参数获得。纵然实际数目从target.result的value属性中获取,首先须要在试图访问value属性前确定保证result是一个灵光的值。假诺result存在,您能够添加result的值到数据数组,然后在result对象上调用continue函数来延续迭代object
store。最终,倘若未有reuslt了,对store数据的迭代甘休,同时数据传递到回调,回调被实践。

于今模块能够从data
store获得全体数据,下二个索要贯彻的函数是负担访问单个记录。

JavaScript

get: function (id, callback) { id = parseInt(id); db.open(function () {
var store = db.getObjectStore(), request = store.get(id);
request.onsuccess = function (e){ callback(e.target.result); }; }); },

1
2
3
4
5
6
7
8
9
10
11
get: function (id, callback) {
    id = parseInt(id);
    db.open(function () {
        var
            store = db.getObjectStore(),
            request = store.get(id);
        request.onsuccess = function (e){
            callback(e.target.result);
        };
    });
},

get函数执行的首先步操作是将id参数的值转换为多个整数。取决于函数被调用时,字符串或整数都大概传递给函数。这几个达成跳过了对如果所给的字符串无法转换到整数该如何做的情形的处理。1旦二个id值准备好了,数据库打开了和object
store能够访问了。获取访问get请求出现了。请求成功时,通过传播e.target.result来施行回调。它(e.target.result)是通过调用get函数到手的单条记录。

前日保存和甄选操作已经出现了,该模块还索要从object store移除数量。

JavaScript

‘delete’: function (id, callback) { id = parseInt(id); db.open(function
() { var mode = ‘readwrite’, store, request; store =
db.getObjectStore(mode); request = store.delete(id); request.onsuccess =
callback; }); },

1
2
3
4
5
6
7
8
9
10
11
‘delete’: function (id, callback) {
    id = parseInt(id);
    db.open(function () {
        var
            mode = ‘readwrite’,
            store, request;
        store = db.getObjectStore(mode);
        request = store.delete(id);
        request.onsuccess = callback;
    });
},

delete函数的名号用单引号,因为delete是JavaScript的保留字。那能够由你来支配。您能够挑选命名函数为del或其余名目,但是delete用在这些模块为了API尽恐怕好的抒发。

传递给delete函数的参数是指标的id和三个回调函数。为了有限支撑那么些完毕简单,delete函数约定id的值为整数。您能够挑选创制三个更加强健的兑现来处理id值不可能分析成整数的不当例子的回调,但为了带领原因,代码示例是假意的。

只要id值能确认保障转换到贰个整数,数据库被打开,一个可写的object
store获得,delete函数字传送入id值被调用。当呼吁成功时,将执行回调函数。

在好几意况下,您或然须求删除三个object
store的具有的笔录。在那种状态下,您访问store同时排除全体内容。

JavaScript

deleteAll: function (callback) { db.open(function () { var mode, store,
request; mode = ‘readwrite’; store = db.getObjectStore(mode); request =
store.clear(); request.onsuccess = callback; }); }

1
2
3
4
5
6
7
8
9
deleteAll: function (callback) {
    db.open(function () {
        var mode, store, request;
        mode = ‘readwrite’;
        store = db.getObjectStore(mode);
        request = store.clear();
        request.onsuccess = callback;
    });
}

此间deleteAll函数负责打开数据库和做客object
store的二个可写实例。1旦store可用,三个新的伸手通过调用clear函数来制造。1旦clear操作成功,回调函数被实施。

开拓数据库的呼吁生命周期

IndexedDB使用事件生命周期管理数据库的开拓和配备操作。图二演示了一个打开的乞请在必然的环境下发生upgrade
need事件。

图片 9

图2:IndexedDB打开请求的生命周期

怀有与数据库的互相开端于1个开辟的乞请。试图打开数据库时,您必须传递3个被呼吁数据库的版本号的整数值。在打开请求时,浏览器相比你传入的用于打开请求的版本号与实际数据库的版本号。假设所请求的版本号高于浏览器中当前的版本号(只怕今后不曾存在的数据库),upgrade
needed事件触发。在uprade
need事件之间,你有机遇通过抬高或移除stores,键和索引来操纵object stores。

即使所请求的数据库版本号和浏览器的当下版本号一致,恐怕升级进度一挥而就,3个开拓的数据库将回来给调用者。

设计规范

IndexedDB的架构很像在一些风靡的劳动器端NOSQL数据库实现中的设计规范类型。面向对象数据经过object
stores(对象仓库)实行持久化,全部操作基于请求同时在业务限制内执行。事件生命周期使您可见支配数据库的配置,错误通过荒谬冒泡来使用API管理。

IndexedDB是还是不是合乎自己的应用程序?

近期最根本的标题:“IndexedDB是或不是切合笔者的应用程序?“像以后同等,答案是早晚的:“视意况而定。“首先当你打算在客户端保存数据时,你会设想HTML五本地存款和储蓄。本地存款和储蓄获得大面积浏览器的辅助,有尤其不难使用的API。简单有其优势,但其逆风局是无能为力支撑复杂的搜索策略,存储多量的数额,并提供业务支持。

IndexedDB是3个数据库。所以,当您想为客户端做出决定,思虑你怎么着在服务端采取1个持久化介质的数据库。你或然会问自个儿有个别题材来帮助控制客户端数据库是或不是顺应您的应用程序,包蕴:

若果你对在那之中的其余难点回复了“是的”,很有十分大大概,IndexedDB是您的应用程序的1个很好的候选。

结论

乘势应用程序的急需的增高,你会意识在客户端高效存储大批量的多少的优势。IndexedDB是足以在浏览器中一贯运用且援救异步事务的文书档案数据库达成。固然浏览器的支撑大概还是无法维系,但在适度的情景下,集成IndexedDB的Web应用程序具有强大的客户端数据的走访能力。

在超过53%状态下,全数针对IndexedDB编写的代码是后天基于请求和异步的。官方正规有同步API,不过那种IndexedDB只适合web
worker的左右文中使用。那篇小说发布时,还并未有浏览器达成的一块格式的IndexedDB
API。

一定要力保代码在任何函数域外对厂商特定的indexedDB, IDBTransaction, and
IDBKeyRange实例举行了规范化且使用了适度从紧形式。那允许你防止浏览器错误,当在strict
mode下解析脚本时,它不会容许你对那个对象重新赋值。

您无法不确定保证只传递正整数的本子号给数据库。传递到版本号的小数值会4舍5入。由此,如果您的数据库最近版本一,您打算访问壹.二版本,upgrade-needed事件不会接触,因为版本号最后评估是一致的。

登时施行函数表达式(IIFE)有时叫做分裂的名字。有时能够看出那样的代码社团办公室法,它叫做self-executing
anonymous functions(自推行匿名函数)或self-invoked anonymous
functions(自调用匿名函数)。为进一步表明那个名称相关的打算和含义,请阅读Ben
Alman的小说Immediately Invoked Function Expression (IIFE) 。

Listing 1: Implementing the getAll function

JavaScript

getAll: function (callback) { db.open(function () { var store =
db.getObjectStore(), cursor = store.openCursor(), data = [];
cursor.onsuccess = function (e) { var result = e.target.result; if
(result && result !== null) { data.push(result.value);
result.continue(); } else { callback(data); } }; }); },

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
getAll: function (callback) {
 
    db.open(function () {
 
        var
            store = db.getObjectStore(),
            cursor = store.openCursor(),
            data = [];
 
        cursor.onsuccess = function (e) {
 
            var result = e.target.result;
 
            if (result &&
                result !== null) {
 
                data.push(result.value);
                result.continue();
 
            } else {
 
                callback(data);
            }
        };
 
    });
},

Listing 2: Full source for database-specific code
(index.db.js)

JavaScript

// index.db.js ; window.indexedDB = window.indexedDB ||
window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;
window.IDBTransaction = window.IDBTransaction ||
window.webkitIDBTransaction || window.msIDBTransaction;
window.IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange ||
window.msIDBKeyRange; (function(window){ ‘use strict’; var db = {
version: 1, // important: only use whole numbers! objectStoreName:
‘tasks’, instance: {}, upgrade: function (e) { var _db =
e.target.result, names = _db.objectStoreNames, name =
db.objectStoreName; if (!names.contains(name)) { _db.createObjectStore(
name, { keyPath: ‘id’, autoIncrement: true }); } }, errorHandler:
function (error) { window.alert(‘error: ‘ + error.target.code);
debugger; }, open: function (callback) { var request =
window.indexedDB.open( db.objectStoreName, db.version); request.onerror
= db.errorHandler; request.onupgradeneeded = db.upgrade;
request.onsuccess = function (e) { db.instance = request.result;
db.instance.onerror = db.errorHandler; callback(); }; }, getObjectStore:
function (mode) { var txn, store; mode = mode || ‘readonly’; txn =
db.instance.transaction( [db.objectStoreName], mode); store =
txn.objectStore( db.objectStoreName); return store; }, save: function
(data, callback) { db.open(function () { var store, request, mode =
‘readwrite’; store = db.getObjectStore(mode), request = data.id ?
store.put(data) : store.add(data); request.onsuccess = callback; }); },
getAll: function (callback) { db.open(function () { var store =
db.getObjectStore(), cursor = store.openCursor(), data = [];
cursor.onsuccess = function (e) { var result = e.target.result; if
(result && result !== null) { data.push(result.value);
result.continue(); } else { callback(data); } }; }); }, get: function
(id, callback) { id = parseInt(id); db.open(function () { var store =
db.getObjectStore(), request = store.get(id); request.onsuccess =
function (e){ callback(e.target.result); }; }); }, ‘delete’: function
(id, callback) { id = parseInt(id); db.open(function () { var mode =
‘readwrite’, store, request; store = db.getObjectStore(mode); request =
store.delete(id); request.onsuccess = callback; }); }, deleteAll:
function (callback) { db.open(function () { var mode, store, request;
mode = ‘readwrite’; store = db.getObjectStore(mode); request =
store.clear(); request.onsuccess = callback; }); } }; window.app =
window.app || {}; window.app.db = db; }(window));

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
// index.db.js
 
;
 
window.indexedDB = window.indexedDB ||
                   window.mozIndexedDB ||
                   window.webkitIndexedDB ||
                   window.msIndexedDB;
 
window.IDBTransaction = window.IDBTransaction ||
                   window.webkitIDBTransaction ||
                   window.msIDBTransaction;
 
window.IDBKeyRange = window.IDBKeyRange ||
                   window.webkitIDBKeyRange ||
                   window.msIDBKeyRange;
 
(function(window){
 
    ‘use strict’;
 
    var db = {
 
        version: 1, // important: only use whole numbers!
 
        objectStoreName: ‘tasks’,
 
        instance: {},
 
        upgrade: function (e) {
 
            var
                _db = e.target.result,
                names = _db.objectStoreNames,
                name = db.objectStoreName;
 
            if (!names.contains(name)) {
 
                _db.createObjectStore(
                    name,
                    {
                        keyPath: ‘id’,
                        autoIncrement: true
                    });
            }
        },
 
        errorHandler: function (error) {
            window.alert(‘error: ‘ + error.target.code);
            debugger;
        },
 
        open: function (callback) {
 
            var request = window.indexedDB.open(
                db.objectStoreName, db.version);
 
            request.onerror = db.errorHandler;
 
            request.onupgradeneeded = db.upgrade;
 
            request.onsuccess = function (e) {
 
                db.instance = request.result;
 
                db.instance.onerror =
                    db.errorHandler;
 
                callback();
            };
        },
 
        getObjectStore: function (mode) {
 
            var txn, store;
 
            mode = mode || ‘readonly’;
 
            txn = db.instance.transaction(
                [db.objectStoreName], mode);
 
            store = txn.objectStore(
                db.objectStoreName);
 
            return store;
        },
 
        save: function (data, callback) {
 
            db.open(function () {
 
                var store, request,
                    mode = ‘readwrite’;
 
                store = db.getObjectStore(mode),
 
                request = data.id ?
                    store.put(data) :
                    store.add(data);
 
                request.onsuccess = callback;
            });
        },
 
        getAll: function (callback) {
 
            db.open(function () {
 
                var
                    store = db.getObjectStore(),
                    cursor = store.openCursor(),
                    data = [];
 
                cursor.onsuccess = function (e) {
 
                    var result = e.target.result;
 
                    if (result &&
                        result !== null) {
 
                        data.push(result.value);
                        result.continue();
 
                    } else {
 
                        callback(data);
                    }
                };
 
            });
        },
 
        get: function (id, callback) {
 
            id = parseInt(id);
 
            db.open(function () {
 
                var
                    store = db.getObjectStore(),
                    request = store.get(id);
 
                request.onsuccess = function (e){
                    callback(e.target.result);
                };
            });
        },
 
        ‘delete’: function (id, callback) {
 
            id = parseInt(id);
 
            db.open(function () {
 
                var
                    mode = ‘readwrite’,
                    store, request;
 
                store = db.getObjectStore(mode);
 
                request = store.delete(id);
 
                request.onsuccess = callback;
            });
        },
 
        deleteAll: function (callback) {
 
            db.open(function () {
 
                var mode, store, request;
 
                mode = ‘readwrite’;
                store = db.getObjectStore(mode);
                request = store.clear();
 
                request.onsuccess = callback;
            });
 
        }
    };
 
    window.app = window.app || {};
    window.app.db = db;
 
}(window));

Listing 3: Full source for user interface-specific code
(index.ui.js)

JavaScript

// index.ui.js ; (function ($, Modernizr, app) { ‘use strict’;
$(function(){ if(!Modernizr.indexeddb){
$(‘#unsupported-message’).show(); $(‘#ui-container’).hide(); return; }
var $deleteAllBtn = $(‘#delete-all-btn’), $titleText =
$(‘#title-text’), $notesText = $(‘#notes-text’), $idHidden =
$(‘#id-hidden’), $clearButton = $(‘#clear-button’), $saveButton =
$(‘#save-button’), $listContainer = $(‘#list-container’),
$noteTemplate = $(‘#note-template’), $emptyNote = $(‘#empty-note’);
var addNoTasksMessage = function(){ $listContainer.append(
$emptyNote.html()); }; var bindData = function (data) {
$listContainer.html(”); if(data.length === 0){ addNoTasksMessage();
return; } data.forEach(function (note) { var m = $noteTemplate.html(); m
= m.replace(/{ID}/g, note.id); m = m.replace(/{TITLE}/g, note.title);
$listContainer.append(m); }); }; var clearUI = function(){
$titleText.val(”).focus(); $notesText.val(”); $idHidden.val(”); }; //
select individual item $listContainer.on(‘click’, ‘a[data-id]’,
function (e) { var id, current; e.preventDefault(); current =
e.currentTarget; id = $(current).attr(‘data-id’); app.db.get(id,
function (note) { $titleText.val(note.title); $notesText.val(note.text);
$idHidden.val(note.id); }); return false; }); // delete item
$listContainer.on(‘click’, ‘i[data-id]’, function (e) { var id,
current; e.preventDefault(); current = e.currentTarget; id =
$(current).attr(‘data-id’); app.db.delete(id, function(){
app.db.getAll(bindData); clearUI(); }); return false; });
$clearButton.click(function(e){ e.preventDefault(); clearUI(); return
false; }); $saveButton.click(function (e) { var title =
$titleText.val(); if (title.length === 0) { return; } var note = {
title: title, text: $notesText.val() }; var id = $idHidden.val(); if(id
!== ”){ note.id = parseInt(id); } app.db.save(note, function(){
app.db.getAll(bindData); clearUI(); }); }); $deleteAllBtn.click(function
(e) { e.preventDefault(); app.db.deleteAll(function () {
$listContainer.html(”); addNoTasksMessage(); clearUI(); }); return
false; }); app.db.errorHandler = function (e) { window.alert(‘error: ‘ +
e.target.code); debugger; }; app.db.getAll(bindData); }); }(jQuery,
Modernizr, window.app));

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
// index.ui.js
 
;
 
(function ($, Modernizr, app) {
 
    ‘use strict’;
 
    $(function(){
 
        if(!Modernizr.indexeddb){
            $(‘#unsupported-message’).show();
            $(‘#ui-container’).hide();
            return;
        }
 
        var
          $deleteAllBtn = $(‘#delete-all-btn’),
          $titleText = $(‘#title-text’),
          $notesText = $(‘#notes-text’),
          $idHidden = $(‘#id-hidden’),
          $clearButton = $(‘#clear-button’),
          $saveButton = $(‘#save-button’),
          $listContainer = $(‘#list-container’),
          $noteTemplate = $(‘#note-template’),
          $emptyNote = $(‘#empty-note’);
 
        var addNoTasksMessage = function(){
            $listContainer.append(
                $emptyNote.html());
        };
 
        var bindData = function (data) {
 
            $listContainer.html(”);
 
            if(data.length === 0){
                addNoTasksMessage();
                return;
            }
 
            data.forEach(function (note) {
              var m = $noteTemplate.html();
              m = m.replace(/{ID}/g, note.id);
              m = m.replace(/{TITLE}/g, note.title);
              $listContainer.append(m);
            });
        };
 
        var clearUI = function(){
            $titleText.val(”).focus();
            $notesText.val(”);
            $idHidden.val(”);
        };
 
        // select individual item
        $listContainer.on(‘click’, ‘a[data-id]’,
 
            function (e) {
 
                var id, current;
 
                e.preventDefault();
 
                current = e.currentTarget;
                id = $(current).attr(‘data-id’);
 
                app.db.get(id, function (note) {
                    $titleText.val(note.title);
                    $notesText.val(note.text);
                    $idHidden.val(note.id);
                });
 
                return false;
            });
 
        // delete item
        $listContainer.on(‘click’, ‘i[data-id]’,
 
            function (e) {
 
                var id, current;
 
                e.preventDefault();
 
                current = e.currentTarget;
                id = $(current).attr(‘data-id’);
 
                app.db.delete(id, function(){
                    app.db.getAll(bindData);
                    clearUI();
                });
 
                return false;
        });
 
        $clearButton.click(function(e){
            e.preventDefault();
            clearUI();
            return false;
        });
 
        $saveButton.click(function (e) {
 
            var title = $titleText.val();
 
            if (title.length === 0) {
                return;
            }
 
            var note = {
                title: title,
                text: $notesText.val()
            };
 
            var id = $idHidden.val();
 
            if(id !== ”){
                note.id = parseInt(id);
            }
 
            app.db.save(note, function(){
                app.db.getAll(bindData);
                clearUI();
            });
        });
 
        $deleteAllBtn.click(function (e) {
 
            e.preventDefault();
 
            app.db.deleteAll(function () {
                $listContainer.html(”);
                addNoTasksMessage();
                clearUI();
            });
 
            return false;
        });
 
        app.db.errorHandler = function (e) {
            window.alert(‘error: ‘ + e.target.code);
            debugger;
        };
 
        app.db.getAll(bindData);
 
    });
 
}(jQuery, Modernizr, window.app));

Listing 3: Full HTML source (index.html)

JavaScript

<!doctype html> <html lang=”en-US”> <head> <meta
charset=”utf-8″> <meta http-equiv=”X-UA-Compatible”
content=”IE=edge”> <title>Introduction to
IndexedDB</title> <meta name=”description”
content=”Introduction to IndexedDB”> <meta name=”viewport”
content=”width=device-width, initial-scale=1″> <link
rel=”stylesheet”
href=”//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css”>
<link rel=”stylesheet” href=”//cdnjs.cloudflare.com/ajax/libs
/font-awesome/4.1.0/css/font-awesome.min.css” > <link
rel=”stylesheet” href=”//cdnjs.cloudflare.com/ajax/libs
/font-awesome/4.1.0/fonts/FontAwesome.otf” > <link
rel=”stylesheet” href=”//cdnjs.cloudflare.com/ajax/libs
/font-awesome/4.1.0/fonts/fontawesome-webfont.eot” > <link
rel=”stylesheet” href=”//cdnjs.cloudflare.com/ajax/libs
/font-awesome/4.1.0/fonts/fontawesome-webfont.svg” > <link
rel=”stylesheet” href=”//cdnjs.cloudflare.com/ajax/libs
/font-awesome/4.1.0/fonts/fontawesome-webfont.ttf” > <link
rel=”stylesheet” href=”//cdnjs.cloudflare.com/ajax/libs
/font-awesome/4.1.0/fonts/fontawesome-webfont.woff” > <style>
h1 { text-align: center; color:#999; } ul li { font-size: 1.35em;
margin-top: 1em; margin-bottom: 1em; } ul li.small { font-style: italic;
} footer { margin-top: 25px; border-top: 1px solid #eee; padding-top:
25px; } i[data-id] { cursor: pointer; color: #eee; }
i[data-id]:hover { color: #c75a6d; } .push-down { margin-top: 25px; }
#save-button { margin-left: 10px; } </style> <script
src=”//cdnjs.cloudflare.com/ajax/libs/modernizr /2.8.2/modernizr.min.js”
></script> </head> <body class=”container”>
<h1>Tasks</h1> <div id=”unsupported-message” class=”alert
alert-warning” style=”display:none;”> <b>Aww snap!</b>
Your browser does not support indexedDB. </div> <div
id=”ui-container” class=”row”> <div class=”col-sm-3″> <a
href=”#” id=”delete-all-btn” class=”btn-xs”> <i class=”fa
fa-trash-o”></i> Delete All</a> <hr/> <ul
id=”list-container” class=”list-unstyled”></ul> </div>
<div class=”col-sm-8 push-down”> <input type=”hidden”
id=”id-hidden” /> <input id=”title-text” type=”text”
class=”form-control” tabindex=”1″ placeholder=”title” autofocus
/><br /> <textarea id=”notes-text” class=”form-control”
tabindex=”2″ placeholder=”text”></textarea> <div
class=”pull-right push-down”> <a href=”#” id=”clear-button”
tabindex=”4″>Clear</a> <button id=”save-button” tabindex=”3″
class=”btn btn-default btn-primary”> <i class=”fa
fa-save”></i> Save</button> </div> </div>
</div> <footer class=”small text-muted text-center”>by <a
href=”http://craigshoemaker.net” target=”_blank”>Craig
Shoemaker</a> <a href=”http://twitter.com/craigshoemaker
target=”_blank”> <i class=”fa fa-twitter”></i></a>
</footer> <script id=”note-template” type=”text/template”>
<li> <i data-id=”{ID}” class=”fa fa-minus-circle”></i>
<a href=”#” data-id=”{ID}”>{TITLE}</a> </li>
</script> <script id=”empty-note” type=”text/template”>
<li class=”text-muted small”>No tasks</li> </script>
<script src=”//ajax.googleapis.com/ajax/libs
/jquery/1.11.1/jquery.min.js”></script> <script
src=”index.db.js” type=”text/javascript”></script> <script
src=”index.ui.js” type=”text/javascript”></script>
</body> </html>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
<!doctype html>
<html lang="en-US">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <title>Introduction to IndexedDB</title>
        <meta name="description"
              content="Introduction to IndexedDB">
        <meta name="viewport"
              content="width=device-width, initial-scale=1">
        <link rel="stylesheet"
              href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
        <link rel="stylesheet"
              href="//cdnjs.cloudflare.com/ajax/libs
/font-awesome/4.1.0/css/font-awesome.min.css" >
        <link rel="stylesheet"
              href="//cdnjs.cloudflare.com/ajax/libs
/font-awesome/4.1.0/fonts/FontAwesome.otf" >
        <link rel="stylesheet"
              href="//cdnjs.cloudflare.com/ajax/libs
/font-awesome/4.1.0/fonts/fontawesome-webfont.eot" >
        <link rel="stylesheet"
              href="//cdnjs.cloudflare.com/ajax/libs
/font-awesome/4.1.0/fonts/fontawesome-webfont.svg" >
        <link rel="stylesheet"
              href="//cdnjs.cloudflare.com/ajax/libs
/font-awesome/4.1.0/fonts/fontawesome-webfont.ttf" >
        <link rel="stylesheet"
              href="//cdnjs.cloudflare.com/ajax/libs
/font-awesome/4.1.0/fonts/fontawesome-webfont.woff" >
        <style>
            h1 {
                text-align: center;
                color:#999;
            }
 
            ul li {
                font-size: 1.35em;
                margin-top: 1em;
                margin-bottom: 1em;
            }
 
            ul li.small {
                font-style: italic;
            }
 
            footer {
                margin-top: 25px;
                border-top: 1px solid #eee;
                padding-top: 25px;
            }
 
            i[data-id] {
                cursor: pointer;
                color: #eee;
            }
 
            i[data-id]:hover {
                color: #c75a6d;
            }
 
            .push-down {
                margin-top: 25px;
            }
 
            #save-button {
                margin-left: 10px;
            }
        </style>
        <script src="//cdnjs.cloudflare.com/ajax/libs/modernizr
/2.8.2/modernizr.min.js" ></script>
    </head>
    <body class="container">
        <h1>Tasks</h1>
        <div id="unsupported-message"
             class="alert alert-warning"
             style="display:none;">
            <b>Aww snap!</b> Your browser does not support indexedDB.
        </div>
        <div id="ui-container" class="row">
            <div class="col-sm-3">
 
                <a href="#" id="delete-all-btn" class="btn-xs">
                    <i class="fa fa-trash-o"></i> Delete All</a>
 
                <hr/>
 
                <ul id="list-container" class="list-unstyled"></ul>
 
            </div>
            <div class="col-sm-8 push-down">
 
                <input type="hidden" id="id-hidden" />
 
                <input
                       id="title-text"
                       type="text"
                       class="form-control"
                       tabindex="1"
                       placeholder="title"
                       autofocus /><br />
 
                <textarea
                          id="notes-text"
                          class="form-control"
                          tabindex="2"
                          placeholder="text"></textarea>
 
                <div class="pull-right push-down">
 
                    <a href="#" id="clear-button" tabindex="4">Clear</a>
 
                    <button id="save-button"
                            tabindex="3"
                            class="btn btn-default btn-primary">
                                <i class="fa fa-save"></i> Save</button>
                </div>
            </div>
        </div>
        <footer class="small text-muted text-center">by
            <a href="http://craigshoemaker.net" target="_blank">Craig Shoemaker</a>
            <a href="http://twitter.com/craigshoemaker" target="_blank">
                <i class="fa fa-twitter"></i></a>
        </footer>
        <script id="note-template" type="text/template">
            <li>
                <i data-id="{ID}" class="fa fa-minus-circle"></i>
                <a href="#" data-id="{ID}">{TITLE}</a>
            </li>
        </script>
        <script id="empty-note" type="text/template">
            <li class="text-muted small">No tasks</li>
        </script>
        <script src="//ajax.googleapis.com/ajax/libs
/jquery/1.11.1/jquery.min.js"></script>
        <script src="index.db.js" type="text/javascript"></script>
        <script src="index.ui.js" type="text/javascript"></script>
    </body>
</html>

赞 1 收藏
评论

推行用户界面特定代码

现行反革命有所特定于数据库的代码被封装在app.db模块中,用户界面特定代码能够运用此模块来与数据库交互。用户界面特定代码的完全清单(index.ui.js)能够在清单三中获得,完整的(index.html)页面包车型大巴HTML源代码可以在清单4中赢得。

基于请求

截止那里,有3个再3出现的核心,您可能曾经注意到。对数据库的每一回操作,描述为通过3个伸手打开数据库,访问一个object
store,再持续。IndexedDB
API天生是根据请求的,那也是API异步脾气提示。对于你在数据库执行的历次操作,你不可能不首先为那么些操作成立三个请求。当呼吁达成,你可以响应由请求结果产生的轩然大波和谬误。

本文实现的代码,演示了怎么着利用请求打开数据库,成立1个业务,读取object
store的始末,写入object store,清空object store。

相关文章

发表评论

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

网站地图xml地图