菜单

IndexedDB数据库

2019年3月31日 - XML

前者的数据库:IndexedDB入门

2014/12/27 · 未分类 · IndexedDB

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

应用程序需求多少。对绝半数以上Web应用程序来说,数据在劳动器端组织和保管,客户端通过网络请求获取。随着浏览器变得更为有能力,因而可采用在浏览器存款和储蓄和控制应用程序数据。

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

读到本学科的结尾时,你将熟练IndexedDB的基本概念以及哪些促成三个接纳IndexedDB执行总体的CRUD操作的模块化JavaScript应用程序。让我们略微亲近IndexedDB并开始吧。

什么是IndexedDB

貌似的话,有三种差别品类的数据库:关系型和文档型(也称之为NoSQL或对象)。关周全据库如SQL
Server,MySQL,Oracle的多少存款和储蓄在表中。文书档案数据库如MongoDB,CouchDB,Redis将数据集作为个人对象存款和储蓄。IndexedDB是一个文书档案数据库,它在完全内停放浏览器中的一个沙盒环境中(强制依据(浏览器)同源策略)。图1显得了IndexedDB的数码,显示了数据库的组织

manbetx2.0手机版 1

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

全部的IndexedDB API请参考完整文书档案

介绍

IndexedDB正是二个数据库
其最大的特点是:
运用对象保存数据,而不是采用表来保存数据,同时,它是异步的

规划规范

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

使用办法

对象仓库

object
store是IndexedDB数据库的根基。要是你选拔过关周密据库,常常能够将object
store等价于1个数量库表。Object
stores包涵二个或多个目录,在store中服从一对键/值操作,那提供一种高效稳定数据的措施。

当您安顿四个object
store,你必须为store选用1个键。键在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)艺术打开2个数据库

据书上说事务

差别于一些观念的关全面据库的完成,种种对数据库操作是在叁个事情的左右文中执行的。事务限制三遍影响3个或三个object
stores,你通过传播1个object store名字的数组到创制工作限制的函数来定义。

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

清单2演示了怎么样使用方便的形式开创二个工作,并在那片小说的 Implementing
Database-Specific Code
 部分举行了详细研究。

indexDB.open()艺术的原理

分成三种境况:
1. 传出的数据库不存在
当传入的数据库不设有时,该格局就会创立三个名为name的数据库,并开拓它,此时,会先触发upgradeneeded事件;调用该函数会重临贰个IDBRequest目的,能够在该目的上添加onsuccess事件onerror事件
注意:当打开二个不设有的数据库时会触发upgradeneeded事件,那是触发该事件的一种途径,为何会触发该事件呢?该事件有如何功能?留个问号在那时候,等会解答。

2. 不翼而飞的数据仓库储存在
那里分为三种情形:

听别人说请求

直到那里,有二个频仍出现的大旨,您大概早已注意到。对数据库的每一次操作,描述为经过二个伸手打开数据库,访问2个object
store,再持续。IndexedDB
API天生是依据请求的,那也是API异步脾性提醒。对于你在数据库执行的历次操作,你必须首先为那个操作创制多个请求。当呼吁完结,你可以响应由请求结果产生的风云和谬误。

正文实现的代码,演示了哪些利用请求打开数据库,制造八个政工,读取object
store的始末,写入object store,清空object store。

upgradeneeded事件

触发该事件的准绳:当打开的数据库不设有,可能传播的数据库版本version高于当前版本,则会触发该事件

upgradeneeded事件的效果:当打开了三个数据库之后,供给开发三个名为:指标存款和储蓄空间
的钱物(能够知道为数据便是存放在这么些空间里面,叁个数据库能够创立多少个对象存款和储蓄空间),而
对象存款和储蓄空间 只能在upgradeneeded事件的处理函数中创建

接纳时,注意以下三种景况:

  1. 当大家第一次打开创造数据库时,会触发upgradeneeded事件,我们就须要在中间创立对象存款和储蓄空间

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

注意:借使急需对指标存款和储蓄空间实行修改,那么只可以先将积存在它里面的数据读取出来,再将其删除,然后使用新的选项去创制它,再写入原来的数目

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

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

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

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

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

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

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

开辟数据库的乞请生命周期

IndexedDB使用事件生命周期管理数据库的开拓和配备操作。图2示范了1个开拓的央浼在放任自流的条件下发出upgrade
need事件。

manbetx2.0手机版 2

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

有着与数据库的并行最先于多少个打开的乞请。试图打开数据库时,您必须传递2个被呼吁数据库的版本号的整数值。在打开请求时,浏览器相比你传入的用来打开请求的版本号与实际数据库的版本号。如若所请求的版本号高于浏览器中当前的版本号(只怕未来尚未存在的数据库),upgrade
needed事件触发。在uprade
need事件之间,你有机会通过足够或移除stores,键和索引来操纵object stores。

假使所请求的数据库版本号和浏览器的当下版本号相同,大概升级进程一呵而就,1个开拓的数据库将回来给调用者。

存款和储蓄数据

积存数据有三种办法: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通过荒谬冒泡效果来协理跟踪和管制不当。如若二个一定的呼吁碰到错误,你能够品尝在伸手对象上处理错误,或然你可以允许错误通过调用栈冒泡向上传递。那个冒泡个性,使得你不要求为各种请求完毕特定错误处理操作,而是能够选拔只在叁个更高级别上添加错误处理,它给你二个火候,保持您的错误处理代码简洁。本文中落到实处的例证,是在一个高级别处理错误,以便更细粒度操作发生的别样不当冒泡到通用的错误处理逻辑。

业务和查询操作数据

最简便易行的创办工作的点子是:
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和华为部分支持。即使这些列表的拥护者是扣人心弦的,但它从未报告全体传说。

manbetx2.0手机版 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是多少个客户端数据库,但它当做2个关周到据库的贯彻,使用结构化查询语言(SQL)与数据库通讯。WebSQL的野史充满了波折,但底线是从未有过主流的浏览器厂商对WebSQL继续援救。

如果WebSQL实际上是3个遗弃的技能,为啥还要提它吧?有趣的是,WebSQL在浏览器里拿走巩固的协助。Chrome,
Safari, iOS Safari, and
Android 浏览器都协助。此外,并不是这一个浏览器的风行版本才提供帮助,许多那么些新颖最棒的浏览器以前的本子也得以辅助。有趣的是,借使你为WebSQL添加辅助来支撑IndexedDB,你突然发现,许多浏览器厂商和版本成为支撑浏览器内置数据库的某种化身。

因此,假如你的应用程序真正须要1个客户端数据库,你想要达到的最高级其余运用只怕,当IndexedDB不可用时,恐怕你的应用程序大概看起来需求选拔采纳WebSQL来支撑客户端数据架构。尽管文书档案数据库和关全面据库管理数据有强烈的异样,但假诺您有不易的空洞,就能够利用当地数据库营造贰个应用程序。

键范围

游标也得以承受三个键,相当于通过键来设定游标查找的限制;
代码如下:

<!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中。
//
在该处理程序中,数据库已经拥有先前版本的靶子存款和储蓄,由此不用再次创建那些指标存款和储蓄,只供给创设任何我们须要的目的存款和储蓄,也许
//
从原先版本中删去不在须要的靶子存款和储蓄。假如供给改变当前目的存款和储蓄,则必须先删除旧的目的存款和储蓄,然后在动用新的选项创设。
// 删除旧的靶子存款和储蓄,在其上的消息都会被去除;
//
注意:该事件是绝无仅有1个能够对数据库实行操作的地点,在该事件之中,你对目的存款和储蓄进行删减、修改或移除索引
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’); //
创立3个政工,并定义该工作的操作为 “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是2个数据库。所以,当你想为客户端做出决定,考虑你怎么着在服务端选拔二个持久化介质的数据库。你大概会问本人有些难点来赞助控制客户端数据库是不是合乎您的应用程序,包蕴:

万一你对当中的其他难点回复了“是的”,很有大概,IndexedDB是您的应用程序的2个很好的候选。

使用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显示了正在编纂任务时的应用程序。

manbetx2.0手机版 4

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

manbetx2.0手机版 5

图5:职责列表

manbetx2.0手机版 6

图6:删除任务

manbetx2.0手机版 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));

用这么的布局,能够使那一个应用程序的有所逻辑封装在3个名为app的单对象上。其余,数据库相关的代码在2个叫做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事件在开拓请求实现前触发。这么些模块被设置为只行使3个object
store,所以名字直接定义在那里。最终,实例成员被创建,它用于保存一旦打开请求完结后的数据库当前实例。

接下去的操作是贯彻upgrade
needed事件的事件处理程序。在此间,检查当前object
store的名字来判断请求的object store名是不是存在,若是不设有,创制object
store。

JavaScript

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

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

在这几个事件处理程序里,通过事件参数e.target.result来访问数据库。当前的object
store名称的列表在_db.objectStoreName的字符串数组上。未来,假若object
store不设有,它是因此传递object
store名称和store的键的定义(自增,关联到数码的ID成员)来创立。

模块的下多个效益是用来捕获错误,错误在模块差别的伸手成立时冒泡。

JavaScript

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

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

在此处,errorHandler在二个警告框展现任何不当。那么些函数是假意保持不难,对开发协调,当你学习应用IndexedDB,您能够很简单地看到任何错误(当他们产生时)。当您准备在生养环境使用那些模块,您要求在那个函数中完毕部分错误处理代码来和你的应用程序的上下文打交道。

以往基础完毕了,这一节的其他部分将演示怎么着落到实处对数据库执行一定操作。第3个须要检查的函数是open函数。

JavaScript

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

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

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

要是请求的实例可用,第三步要拓展的行事是安装错误处理程序和进步函数。记住,当数据库被打开时,假诺脚本请求比浏览器里更高版本的数据库(或许只要数据库不设有),升级函数运维。可是,如若请求的数据库版本匹配当前数据库版本同时没有不当,success事件触发。

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

下1个要促成的函数是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的操作都以在1个东西的上下文中执行的。事务请求接受多少个object
store名字的数组。这一个函数此次被布置为只行使三个object
store,然则一旦你须求在事情中操作八个object store,你必要传递四个object
store的名字到数组中。事务函数的第②个参数是2个方式。

一旦事情请求可用,您就足以因而传递须求的object
store名字来调用objectStore函数以取得object
store实例的访问权。那个模块的其它函数使用getObjectStore来获得object
store的访问权。

下三个完成的函数是save函数,执行插入或更新操作,它依据传入的数据是还是不是有三个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的3个可写实例。然后,检查数据对象的ID成员是或不是留存。假如存在ID值,数据必须立异,put函数被调用,它成立持久化请求。不然,若是ID不存在,这是新数据,add请求重回。最后,不管put恐怕add
请求是或不是实施了,success事件处理程序供给安装在回调函数上,来报告调用脚本,一切进展顺遂。

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

在store访问数据时,游标遍历数据库中的每条记下,会触发onsuccess事件处理程序。当每条记下走访时,store的数目足以由此e.target.result事件参数获得。即便实际数目从target.result的value属性中赢得,首先须要在准备访问value属性前确定保证result是一个实用的值。要是result存在,您可以添加result的值到数据数组,然后在result对象上调用continue函数来接二连三迭代object
store。最终,倘诺没有reuslt了,对store数据的迭代结束,同时数据传递到回调,回调被执行。

今昔模块能够从data
store获得全体数据,下一个需求完毕的函数是承受访问单个记录。

JavaScript

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

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

get函数执行的率先步操作是将id参数的值转换为二个整数。取决于函数被调用时,字符串或整数都或许传递给函数。这么些实现跳过了对假若所给的字符串不可能转换来整数该怎么办的景观的拍卖。一旦八个id值准备好了,数据库打开了和object
store能够访问了。获取访问get请求现身了。请求成功时,通过传播e.target.result来实施回调。它(e.target.result)是通过调用get函数到手的单条记录。

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

JavaScript

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

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

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

传送给delete函数的参数是指标的id和四个回调函数。为了保险那几个实现简单,delete函数约定id的值为整数。您能够挑选创造一个更强健的兑现来处理id值不可能分析成整数的荒唐例子的回调,但为了指导原因,代码示例是假意的。

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

在好几情状下,您大概须要删除2个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可用,1个新的央浼通过调用clear函数来创立。一旦clear操作成功,回调函数被实践。

实施用户界面特定代码

当今全部特定于数据库的代码被封装在app.db模块中,用户界面特定代码能够采用此模块来与数据库交互。用户界面特定代码的欧洲经济共同体清单(index.ui.js)可以在清单3中拿走,完整的(index.html)页面包车型大巴HTML源代码能够在清单4中取得。

结论

随着应用程序的必要的滋长,你会发未来客户端高效存款和储蓄大量的数量的优势。IndexedDB是能够在浏览器中央直机关接使用且援救异步事务的文书档案数据库达成。固然浏览器的支撑恐怕或不可能有限扶助,但在适合的气象下,集成IndexedDB的Web应用程序具有强有力的客户端数据的拜访能力。

在大部动静下,全部针对IndexedDB编写的代码是纯天然基于请求和异步的。官方正规有同步API,不过那种IndexedDB只适合web
worker的光景文中使用。这篇小说公布时,还尚无浏览器达成的一Doug式的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

manbetx2.0手机版 8

和讯天涯论坛:@hop_ping
个人主页
·
小编的篇章
·
17

manbetx2.0手机版 9

相关文章

发表评论

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

网站地图xml地图