菜单

IndexedDB数据库

2019年3月28日 - Json

前者的数据库:IndexedDB入门

2014/12/27 · 未分类 · IndexedDB

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

应用程序必要多少。对超越四分之二Web应用程序来说,数据在劳动器端组织和管制,客户端通过网络请求获取。随着浏览器变得尤为有力量,由此可挑选在浏览器存款和储蓄和操纵应用程序数据。

正文向您介绍名为IndexedDB的浏览器端文档数据库。使用lndexedDB,你能够由此惯于在劳动器端数据库大约一模一样的章程开创、读取、更新和删除大量的笔录。请使用本文中可工作的代码版本去体验,完整的源代码能够透过GitHub库找到。

读到本学科的末段时,你将熟习IndexedDB的基本概念以及哪些完毕2个行使IndexedDB执行总体的CRUD操作的模块化JavaScript应用程序。让大家有点亲近IndexedDB并先河吧。

什么是IndexedDB

诚如的话,有三种差异品类的数据库:关系型和文书档案型(也称为NoSQL或对象)。关周到据库如SQL
Server,MySQL,Oracle的多少存款和储蓄在表中。文书档案数据库如MongoDB,CouchDB,Redis将数据集作为个体对象存款和储蓄。IndexedDB是一个文书档案数据库,它在完全内放置浏览器中的二个沙盒环境中(强制根据(浏览器)同源策略)。图1出示了IndexedDB的数目,体现了数据库的布局

图片 1

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

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

介绍

IndexedDB就是四个数据库
其最大的风味是:
利用对象保存数据,而不是应用表来保存数据,同时,它是异步的

统一筹划规范

IndexedDB的架构很像在一部分风靡的劳务器端NOSQL数据库达成中的设计指南类型。面向对象数据通过object
stores(对象仓库)实行持久化,全体操作基于请求同时在作业限制内执行。事件生命周期使你能够控制数据库的配置,错误通过荒谬冒泡来使用API管理。

利用方法

指标仓库

object
store是IndexedDB数据库的底蕴。假若你使用过关周详据库,平时能够将object
store等价于叁个数目库表。Object
stores包蕴3个或四个目录,在store中根据一对键/值操作,那提供一种高效稳定数据的方式。

当您布置3个object
store,你无法不为store采取贰个键。键在store中能够以“in-line”或“out-of-line”的不二法门存在。in-line键通过在数码对象上引用path来维系它在object
store的唯一性。为了印证那或多或少,想想一个总结电子邮件地址属性Person对象。您能够配备你的store使用in-line键emailAddress,它能担保store(持久化对象中的数据)的唯一性。其余,out-of-line键通过单独于数据的值识别唯一性。在那种状态下,你能够把out-of-line键比作二个整数值,它(整数值)在关周详据库中担任记录的主键。

图1显示了职务数据保存在任务的object
store,它使用in-line键。在那一个案例中,键对应于对象的ID值。

总是数据库

要利用它必须先打开,通过 indexDB.open(name, version)措施打开一个数据库

听新闻说事务

不一致于一些价值观的关周到据库的完结,每八个对数据库操作是在一个业务的光景文中执行的。事务限制三次影响1个或多个object
stores,你通过传播三个object store名字的数组到创制工作限制的函数来定义。

创办工作的第三个参数是事情方式。当呼吁1个事务时,必须决定是依据只读依然读写形式请求访问。事务是能源密集型的,所以要是你不须求更改data
store中的数据,你只供给以只读方式对object stores集合实行呼吁访问。

清单2演示了哪些接纳合适的情势创建二个业务,并在那片文章的 Implementing
Database-Specific Code
 部分举办了详尽谈论。

indexDB.open()方法的规律

分成二种境况:
1. 传来的数据库不存在
当传入的数据库不设有时,该办法就会创制三个名为name的数据库,并开拓它,此时,会先触发upgradeneeded事件;调用该函数会再次回到三个IDBRequest对象,能够在该对象上添加onsuccess事件onerror事件
注意:当打开二个不设有的数据库时会触发upgradeneeded事件,那是触发该事件的一种途径,为啥会触发该事件吧?该事件有啥样效劳?留个难点在那时,等会解答。

2. 传来的数据仓库储存在
此间分为两种情景:

依照请求

直至那里,有一个反复出现的大旨,您恐怕早就注意到。对数据库的每一次操作,描述为通过1个请求打开数据库,访问3个object
store,再持续。IndexedDB
API天生是基于请求的,那也是API异步本性提醒。对于你在数据库执行的历次操作,你必须首先为这几个操作创设三个呼吁。当呼吁完成,你能够响应由请求结果爆发的事件和错误。

本文达成的代码,演示了哪些选拔请求打开数据库,创立3个政工,读取object
store的内容,写入object store,清空object store。

upgradeneeded事件

触发该事件的规则:当打开的数据库不设有,恐怕传播的数据库版本version高于当前版本,则会触发该事件

upgradeneeded事件的意义:当打开了2个数据库之后,须要开发3个名为:目的存款和储蓄空间
的钱物(能够精通为多少就是存放在这几个空间里面,1个数据库能够创造三个对象存款和储蓄空间),而
对象存款和储蓄空间 只能在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});
}

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

IndexedDB使用事件生命周期管理数据库的开辟和配置操作。图2示范了3个开拓的乞求在早晚的环境下发出upgrade
need事件。

图片 2

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

有着与数据库的互动开始于多个开拓的乞请。试图打开数据库时,您必须传递3个被呼吁数据库的本子号的整数值。在开辟请求时,浏览器相比你传入的用于打开请求的版本号与事实上数据库的版本号。假设所请求的版本号高于浏览器中当前的版本号(或许以往尚未存在的数据库),upgrade
needed事件触发。在uprade
need事件之间,你有时机通过添加或移除stores,键和索引来操纵object stores。

倘诺所请求的数据库版本号和浏览器的如今版本号一样,只怕升级进程做到,一个开辟的数据库将回到给调用者。

积存数据

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

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

不当冒泡

本来,有时候,请求或然不会按预想完结。IndexedDB
API通过荒谬冒泡效果来援救跟踪和保管不当。假使二个一定的呼吁境遇错误,你能够尝试在央浼对象上处理错误,或然你能够允许错误通过调用栈冒泡向上传递。这几个冒泡性情,使得你不要求为各样请求完结特定错误处理操作,而是能够挑选只在1个更高级别上添加错误处理,它给你三个火候,保持您的错误处理代码简洁。本文中完结的事例,是在三个高级别处理错误,以便更细粒度操作产生的别的不当冒泡到通用的错误处理逻辑。

工作和查询操作数据

最简易的创导工作的主意是:
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事件处理程序中才能访问到数码

浏览器帮衬

大概在支付Web应用程序最重庆大学的题材是:“浏览器是或不是援助本人想要做的?“即使浏览器对IndexedDB的支撑在连续增强,选取率并不是大家所期待的这样普遍。图3显得了caniuse.com网站的告知,扶助IndexedDB的为66%多一丢丢。最新版本的银狐,Chrome,Opera,Safar,iOS
Safari,和Android完全扶助IndexedDB,Internet
Explorer和Samsung部分协理。即使那么些列表的拥护者是令人鼓舞的,但它并未报告全体传说。

图片 3

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

只有可怜新本子的Safari和iOS Safari
帮助IndexedDB。据caniuse.com展现,那只占大致0.01%的天下浏览器选取。IndexedDB不是三个你以为能够理所当然获得援救的当代Web
API,然而你将便捷会如此认为。

利用游标查询数据

运用工作可以直接通过
已知的键检索单个对象。而在急需摸索四个对象时,则需要在业务内创制游标。

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

如下:

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才起来落到实处,它是在WebSQL兑现之后的一种新方式。类似IndexedDB,WebSQL是二个客户端数据库,但它当作一个关周密据库的落到实处,使用结构化查询语言(SQL)与数据库通讯。WebSQL的野史充满了弯曲,但底线是未曾主流的浏览器厂商对WebSQL继续扶助。

假如WebSQL实际上是3个抛弃的技巧,为何还要提它吗?有趣的是,WebSQL在浏览器里获得逐步的支撑。Chrome,
Safari, iOS Safari, and
Android 浏览器都接济。其余,并不是那些浏览器的最新版本才提供支撑,许多那个新型最棒的浏览器此前的版本也足以支撑。有趣的是,借使您为WebSQL添加扶助来帮助IndexedDB,你突然发现,许多浏览器厂商和本子成为支撑浏览器内置数据库的某种化身。

故此,假使你的应用程序真正需求3个客户端数据库,你想要达到的最高级其余利用大概,当IndexedDB不可用时,也许你的应用程序大概看起来供给选拔采纳WebSQL来帮忙客户端数据架构。固然文书档案数据库和关周详据库管理数据有闻名海外的差距,但如果您有不错的望梅止渴,就能够动用当地数据库构建三个应用程序。

键范围

游标也能够承受1个键,也正是因而键来设定游标查找的限定;
代码如下:

<!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中。
//
在该处理程序中,数据库已经具备先前版本的对象存储,由此不必再一次创制那几个目的存款和储蓄,只必要成立任何我们须要的靶子存储,或然
//
从从前版本中删除不在要求的目的存款和储蓄。即便须求变更当前指标存款和储蓄,则必须先删除旧的对象存款和储蓄,然后在应用新的选项创造。
// 删除旧的目的存款和储蓄,在其上的音讯都会被剔除;
//
注意:该事件是唯一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’); //
创设3个事物, 并定义该工作的操作为 “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>

IndexedDB是不是相符本身的应用程序?

未来最关键的标题:“IndexedDB是还是不是合乎自个儿的应用程序?“像往常一模一样,答案是必定的:“视情状而定。“首先当你准备在客户端保存数据时,你会考虑HTML5当地存款和储蓄。本地存储获得普遍浏览器的支撑,有分外便于使用的API。简单有其优势,但其劣势是无力回天支撑复杂的检索策略,存款和储蓄大量的多少,并提供业务援救。

IndexedDB是二个数据库。所以,当您想为客户端做出决定,考虑你怎样在服务端选用贰个持久化介质的数据库。你大概会问本人有个别难点来赞助控制客户端数据库是还是不是符合您的应用程序,包含:

即便您对内部的别的难点回答了“是的”,很有恐怕,IndexedDB是您的应用程序的二个很好的候选。

使用IndexedDB

前几天,你早就有时机熟习了部分的总体概念,下一步是从头落到实处基于IndexedDB的应用程序。第二个步骤供给统一IndexedDB在不一致浏览器的贯彻。您能够很不难地抬高各个厂商脾气的选用的检讨,同时在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初始工作。

使用概述

在本教程中,您将学习怎样创造二个利用IndexedDB存款和储蓄数据的模块化JavaScript应用程序。为了了然应用程序是何等工作的,参考图4,它讲述了职责应用程序处于空白状态。从那边您可以为列表添加新义务。图5显得了录入了多少个任务到系统的画面。图6来得怎么删除3个义务,图7显示了正在编辑职责时的应用程序。

图片 4

图4:空白的职分应用程序

图片 5

图5:职分列表

图片 6

图6:删除职分

图片 7

图7:编辑职责
最近您熟谙的应用程序的服从,下一步是发端为网站铺设基础。

铺设基础

以此事例从落到实处如此三个模块开始,它承受从数据库读取数据,插入新的指标,更新现有对象,删除单个对象和提供在二个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对象的积极分子。完整的数据库模块列表见清单2。

Implementing Database-Specific Code

对数据库的各种操作关联着一个先决条件,即有三个开辟的数据库。当数据库正在被打开时,通过检查数据库版本来判断数据库是还是不是需求任何变更。上面的代码显示了模块咋样跟踪当前版本,object
store名、某成员(保存了假诺数据库打开请求达成后的数据库当前实例)。

JavaScript

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

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

在此处,数据库打开请求产生时,模块请求版本1数据库。借使数据库不存在,恐怕版本小于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,您能够很简单地见到其余错误(当他俩爆发时)。当您准备在生养环境使用那几个模块,您须求在这一个函数中贯彻部分错误处理代码来和你的应用程序的上下文打交道。

明天基础完毕了,这一节的别的部分将演示如何落到实处对数据库执行一定操作。第三个需求检讨的函数是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的操作都以在三个事物的内外文中执行的。事务请求接受三个object
store名字的数组。这么些函数这一次被安插为只行使二个object
store,可是即使你要求在事情中操作八个object store,你要求传递多个object
store的名字到数组中。事务函数的第三个参数是四个方式。

要是事情请求可用,您就能够透过传递须要的object
store名字来调用objectStore函数以获取object
store实例的访问权。那几个模块的其余函数使用getObjectStore来收获object
store的访问权。

下1个实现的函数是save函数,执行插入或更新操作,它依照传入的多少是不是有2个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获得全部数据,下3个需求完成的函数是承受访问单个记录。

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参数的值转换为3个整数。取决于函数被调用时,字符串或整数都或许传递给函数。那一个完毕跳过了对如若所给的字符串不可能转换到整数该如何做的情况的拍卖。一旦三个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的值为整数。您能够采用创设1个更硬朗的兑现来拍卖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的三个可写实例。一旦store可用,一个新的恳求通过调用clear函数来成立。一旦clear操作成功,回调函数被实践。

实践用户界面特定代码

当今享有特定于数据库的代码被封装在app.db模块中,用户界面特定代码能够利用此模块来与数据库交互。用户界面特定代码的一体化清单(index.ui.js)能够在清单3中取得,完整的(index.html)页面包车型客车HTML源代码能够在清单4中获得。

结论

随着应用程序的急需的增强,你会发未来客户端高效存款和储蓄多量的数指标优势。IndexedDB是足以在浏览器中一贯运用且扶助异步事务的文书档案数据库达成。固然浏览器的支撑大概否保全,但在适宜的景观下,集成IndexedDB的Web应用程序具有强大的客户端数据的访问能力。

在大多数动静下,全体针对IndexedDB编写的代码是纯天然基于请求和异步的。官方正式有同步API,然则那种IndexedDB只适合web
worker的左右文中使用。这篇文章发表时,还未曾浏览器完结的联合格式的IndexedDB
API。

肯定要确定保证代码在任何函数域外对厂商特定的indexedDB, IDBTransaction, and
IDBKeyRange实例进行了规范化且使用了从严形式。那允许你制止浏览器错误,当在strict
mode下解析脚本时,它不会允许你对那么些对象重新赋值。

你必须保证只传递正整数的版本号给数据库。传递到版本号的小数值会四舍五入。由此,即使你的数据库近日版本1,您准备访问1.2本子,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 收藏
评论

至于笔者:cucr

图片 8

博客园今日头条:@hop_ping
个人主页
·
笔者的小说
·
17

图片 9

相关文章

发表评论

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

网站地图xml地图