菜单

前者的数据库:IndexedDB入门

2019年3月25日 - jQuery

前者的数据库: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是三个文书档案数据库,它在一点一滴内停放浏览器中的三个沙盒环境中(强制依照(浏览器)同源策略)。图1展现了IndexedDB的数量,展现了数据库的组织

图片 1

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

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

介绍

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

统一筹划规范

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

使用形式

对象仓库

object
store是IndexedDB数据库的根底。借使你选拔过关全面据库,平日能够将object
store等价于一个数额库表。Object
stores包蕴1个或三个目录,在store中依照一对键/值操作,那提供一种高效稳定数据的点子。

当你安顿二个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)措施打开二个数据库

根据事务

分歧于一些价值观的关周详据库的兑现,每3个对数据库操作是在一个业务的内外文中执行的。事务限制二次影响三个或多少个object
stores,你通过传播3个object store名字的数组到制造工作限制的函数来定义。

创建工作的第二个参数是工作方式。当呼吁三个事务时,必须控制是比照只读还是读写方式请求访问。事务是财富密集型的,所以只要您不须要更改data
store中的数据,你只供给以只读格局对object stores集合举行呼吁访问。

清单2演示了什么样接纳合适的形式开创二个事情,并在那片文章的 Implementing
Database-Specific Code
 部分开始展览了详尽座谈。

indexDB.open()措施的规律

分成二种意况:
1. 传诵的数据库不设有
当传入的数据库不设有时,该措施就会创建八个名为name的数据库,并打开它,此时,会先触发upgradeneeded事件;调用该函数会重回贰个IDBRequest指标,能够在该对象上添加onsuccess事件onerror事件
注意:当打开2个不存在的数据库时会触发upgradeneeded事件,那是触发该事件的一种途径,为何会触发该事件吧?该事件有如何成效?留个疑问在此时,等会解答。

2. 传开的数据仓库储存在
那边分为二种意况:

依据请求

以至于那里,有二个频仍出现的主旨,您恐怕早已注意到。对数据库的历次操作,描述为经过多少个伸手打开数据库,访问一个object
store,再持续。IndexedDB
API天生是依照请求的,那也是API异步个性提示。对于你在数据库执行的每回操作,你不能够不首先为那个操作创造三个呼吁。当呼吁实现,你可以响应由请求结果发生的轩然大波和谬误。

本文完毕的代码,演示了什么行使请求打开数据库,成立一个工作,读取object
store的内容,写入object store,清空object store。

upgradeneeded事件

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

upgradeneeded事件的效能:当打开了3个数据库之后,须求开辟一个名为:指标存款和储蓄空间
的实物(能够通晓为数量便是存放在那个空间里面,三个数据库能够成立多少个对象存款和储蓄空间),而
对象存储空间 只能在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演示了三个开拓的乞求在早晚的环境下发出upgrade
need事件。

图片 2

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

有着与数据库的交互开首于一个开辟的呼吁。试图打开数据库时,您必须传递八个被呼吁数据库的本子号的整数值。在打开请求时,浏览器相比较你传入的用于打开请求的版本号与事实上数据库的版本号。假如所请求的版本号高于浏览器中当前的版本号(大概以往尚无存在的数据库),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通过荒谬冒泡效果来帮衬跟踪和治本不当。假使3个特定的呼吁蒙受错误,你能够品味在伸手对象上处理错误,恐怕你能够允许错误通过调用栈冒泡向上传递。这些冒泡个性,使得你不须要为各种请求完结特定错误处理操作,而是可以挑选只在三个更高级别上添加错误处理,它给你四个火候,保持您的错误处理代码简洁。本文中落到实处的事例,是在二个高级别处理错误,以便更细粒度操作发生的其余不当冒泡到通用的错误处理逻辑。

工作和查询操作数据

最简易的创导工作的措施是:
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和一加部分帮助。即使这一个列表的维护者是冲动的,但它没有报告全部逸事。

图片 3

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

唯有可怜新本子的Safari和iOS Safari
帮衬IndexedDB。据caniuse.com展现,那只占差不多0.01%的五洲浏览器选择。IndexedDB不是2个您以为可以理所当然获得帮助的现世Web
API,可是你将十分的快会那样认为。

应用游标查询数据

接纳工作能够向来通过
已知的键检索单个对象。而在急需摸索多个目的时,则供给在业务内创设游标。

游标并不会提前收集结果,游标先指向结果中的第1项,在接收查找下一项的授命时,才会针对下一项

如下:

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是贰个客户端数据库,但它作为3个关周全据库的兑现,使用结构化查询语言(SQL)与数据库通讯。WebSQL的历史充满了弯曲,但底线是从未主流的浏览器厂商对WebSQL继续匡助。

假使WebSQL实际上是二个抛弃的技术,为啥还要提它吧?有趣的是,WebSQL在浏览器里得到稳步的援助。Chrome,
Safari, iOS Safari, and
Android 浏览器都帮衬。其余,并不是这一个浏览器的最新版本才提供辅助,许多这几个新式最棒的浏览器此前的本子也得以支撑。有趣的是,假使你为WebSQL添加协助来支撑IndexedDB,你突然意识,许多浏览器厂商和版本成为援助浏览器内置数据库的某种化身。

所以,要是你的应用程序真正须要三个客户端数据库,你想要达到的最高级别的运用大概,当IndexedDB不可用时,大概你的应用程序大概看起来要求选用采用WebSQL来支撑客户端数据架构。即使文书档案数据库和关周到据库管理数据有肯定的反差,但只要您有不利的虚幻,就能够利用当地数据库营造1个应用程序。

键范围

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

<!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’;
// 创建1个数据
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对象的实例
}

// 当创造1个新的数据库 可能 更新已存在数据库的本子,
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’); //
创制1个东西, 并定义该事务的操作为 “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是3个数据库。所以,当你想为客户端做出决定,考虑你怎么在服务端选取二个持久化介质的数据库。你只怕会问本人有个别标题来扶助控制客户端数据库是或不是相符你的应用程序,包含:

一旦你对在那之中的别的难题回复了“是的”,很有恐怕,IndexedDB是你的应用程序的3个很好的候选。

使用IndexedDB

今天,你曾经有机会纯熟了部分的欧洲经济共同体概念,下一步是始于落到实处基于IndexedDB的应用程序。第1个步骤必要统一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初步工作。

选用概述

在本教程中,您将学习如何创制3个选择IndexedDB存款和储蓄数据的模块化JavaScript应用程序。为了打探应用程序是何许做事的,参考图4,它描述了职分应用程序处于空白状态。从这里你能够为列表添加新任务。图5来得了录入了多少个职分到系统的镜头。图6出示怎么删除二个职分,图7呈现了正在编辑职务时的应用程序。

图片 4

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

图片 5

图5:职分列表

图片 6

图6:删除任务

图片 7

图7:编辑职分
近年来你熟习的应用程序的功效,下一步是从头为网站铺设基础。

铺设基础

那一个事例从达成那样1个模块伊始,它承担从数据库读取数据,插入新的靶子,更新现有对象,删除单个对象和提供在3个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在2个警告框呈现其余错误。那个函数是假意保持容易,对开发协调,当你读书运用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的访问权。

下叁个落实的函数是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是3个实惠的值。假诺result存在,您能够添加result的值到数据数组,然后在result对象上调用continue函数来一连迭代object
store。最终,假若没有reuslt了,对store数据的迭代甘休,同时数据传递到回调,回调被实践。

昨天模块能够从data
store得到全部数据,下1个急需贯彻的函数是肩负访问单个记录。

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参数的值转换为二个平头。取决于函数被调用时,字符串或整数都恐怕传递给函数。这几个完毕跳过了对假诺所给的字符串不能够转换到整数该如何做的情景的拍卖。一旦三个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的值为整数。您能够选取创立2个更强健的实现来拍卖id值无法分析成整数的不当例子的回调,但为了指点原因,代码示例是明知故问的。

要是id值能保险转换来1个整数,数据库被打开,三个可写的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地图