菜单

前边三个的数据库:IndexedDB入门

2019年9月28日 - 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:开荒者工具查看一个object
store

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

介绍

IndexedDB正是贰个数据库
其最大的特点是:
行使对象保存数据,并非利用表来保存数据,同一时间,它是异步的

规划指南

IndexedDB的架构很像在局地盛行的服务器端NOSQL数据库完结中的设计指南类型。面向对象数据通过object
stores(对象商旅)进行漫长化,全部操作基于乞求同不时候在事情限制内实行。事件生命周期令你可以调控数据库的安顿,错误通过荒谬冒泡来使用API管理。

运用方法

目的仓库

object
store是IndexedDB数据库的功底。要是你利用过关周全据库,经常能够将object
store等价于一个数量库表。Object
stores包涵三个或四个目录,在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)方法打开八个数据库

据他们说事务

不一样于一些观念的关周到据库的达成,每二个对数据库操作是在一个职业的光景文中实行的。事务限制三遍影响二个或多少个object
stores,你通过传播多少个object store名字的数组到创立职业限制的函数来定义。

创制专门的学业的第二个参数是事情情势。当呼吁一个事务时,必需决定是坚守只读依旧读写格局诉求访谈。事务是财富密集型的,所以只要您无需改换data
store中的数据,你只要求以只读格局对object stores会集实行呼吁访谈。

清单2演示了何等选择十分的格局开创二个作业,并在那片小说的 Implementing
Database-Specific Code
 部分实行了详尽座谈。

indexDB.open()艺术的准则

分为三种状态:
1. 传到的数据库不设有
当传入的数据库不设一时,该格局就能够创立二个名称为name的数据库,并开荒它,此时,会先触发upgradeneeded事件;调用该函数会重返二个IDBRequest目的,能够在该对象上加多onsuccess事件onerror事件
注意:当张开壹个不设有的数据库时会触发upgradeneeded事件,那是触发该事件的一种渠道,为啥会触发该事件吧?该事件有如何效劳?留个疑问在那时候,等会解答。

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示范了四个开荒的央浼在鲜明的意况下产生upgrade
need事件。

图片 2

图2:IndexedDB展开央浼的生命周期

有着与数据库的互动早先于一个展开的伏乞。试图张开数据库时,您必得传递二个被呼吁数据库的本子号的整数值。在开采央求时,浏览器相比较你传入的用于展开乞求的版本号与事实上数据库的版本号。若是所央浼的版本号高于浏览器中当前的版本号(大概未来尚无存在的数据库),upgrade
needed事件触发。在uprade
need事件时期,你有时机通过加多或移除stores,键和索引来垄断(monopoly)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通过荒谬冒泡效果来扶持跟踪和管制不当。假如贰个一定的乞求蒙受错误,你能够品味在呼吁对象上管理错误,可能你能够允许错误通过调用栈冒泡向上传递。这些冒泡性格,使得你无需为各样须求完毕特定错误处理操作,而是能够接纳只在一个更加高等别上增加错误管理,它给你一个机缘,保持您的错误管理代码简洁。本文中贯彻的例子,是在八个高等别管理错误,以便越来越细粒度操作产生的别样错误冒泡到通用的错误管理逻辑。

职业和查询操作数据

最简易的开创职业的格局是:
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和Nokia部分帮衬。固然那一个列表的维护者是扣人心弦的,但它未有报告全部传说。

图片 3

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

唯有可怜新本子的Safari和iOS Safari
帮助IndexedDB。据caniuse.com彰显,这只占差不离0.01%的大千世界浏览器选用。IndexedDB不是多少个你感到能够道理当然是那样的获得协助的现世Web
API,不过你将便捷会那样以为。

应用游标查询数据

运用工作能够平素通过
已知的键检索单个对象。而在急需索求多少个对象时,则需求在作行业内部创立游标。

游标并不会提早采会集果,游标先指向结果中的第一项,在吸收接纳查找下一项的吩咐时,才会针对下一项

如下:

let transaction = db.transaction('customers', 'readwrite'),
let store = transaction.objectStore('customers'),
let request = store.openCursor(null) ; // 这里创建游标
request.onsuccess = function (event) {
  // event.target.result 中保存的是在存储空间中查询到的对象
  // event.target.result 中有几个属性值,可以了解到查询到的对象中的细节,
  // key: 当前访问的对象的键
  // value:当前访问的实际对象
  // primaryKey: 游标使用的键
  // direction:数值,表示游标移动的方向
  let cursor = event.target.result;
  let value, updateRequest, deleteRequest;

  // 这里必须要检查游标中是否有数据
  if (cursor) {
    if (cursor.key === '555-55-5555') {
      value = cursor.value;   // 获取到实际的访问对象
      value.name = 'hexon';   // 修改对象的name属性
      // 调用update()方法可以用指定的对象,更新对象的value
      updateRequest = cursor.update(value);     
      updateRequest.onsuccess = function() {
          // 处理成功
       }
    }
    cursor.continue() ;  // 移动到下一项,会触发下一次请求,同时成功则触发request.onsuccess
  }
}

下边例子中,能够采取cursor.delete()艺术删除当前项

另一种选拔

浏览器帮助本地数据库并非从IndexedDB才起来落到实处,它是在WebSQL完毕之后的一种新点子。类似IndexedDB,WebSQL是三个顾客端数据库,但它看成三个关周到据库的实现,使用结构化查询语言(SQL)与数据库通讯。WebSQL的历史充满了卷曲,但底线是从没有过主流的浏览器商家对WebSQL继续扶助。

假诺WebSQL实际上是三个扬弃的技艺,为何还要提它吧?有意思的是,WebSQL在浏览器里获得稳步的支撑。Chrome,
Safari, iOS Safari, and
Android 浏览器都补助。别的,并非那些浏览器的新星版本才提供支撑,多数那么些新型最棒的浏览器在此之前的本子也得以扶助。风趣的是,尽管您为WebSQL增加协理来支撑IndexedDB,你忽地发掘,相当多浏览器商家和本子成为协助浏览器内置数据库的某种化身。

就此,借使您的应用程序真正要求二个顾客端数据库,你想要到达的最高端其余运用大概,当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中。
//
在该管理程序中,数据库已经具备先前版本的目的存款和储蓄,因而不要再一次创立那个目的存款和储蓄,只供给成立任何我们必要的靶子存款和储蓄,或然
//
从在此之前版本中删除不在须求的目的存款和储蓄。借使须要更动当前目的存款和储蓄,则必需先删除旧的靶子存款和储蓄,然后在应用新的选项创制。
// 删除旧的对象存款和储蓄,在其上的音信都会被去除;
//
注意:该事件是唯一四个可以对数据库举办操作的地点,在该事件之中,你对目的存款和储蓄进行删除、修改或移除索引
request.onupgradeneeded = function(event) {
console.log(‘onupgradeneeded’);
var db = event.target.result;

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

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

}

function save(data) {
///
对于数据库的指标存款和储蓄空间中数据的读取或修改数据,都要经过事物来组织全数操作
// 最轻松易行的开创事物的格局是:var transaction = db.transaction();
let transaction = db.transaction(‘customers’, ‘readwrite’); //
创制四个作业,并定义该职业的操作为 “readwrite” ,并回到其索引
let store = transaction.objectStore(‘customers’); //
获得索引后,使用objectStore()方法并传到存款和储蓄空间的名称,就可以访谈特定的积攒空间

for (var i in customerData) {
  let req = store.put(customerData[i]);   // 往一个存储空间中添加数据
}

transaction.oncomplete = function(event) {
  console.log(event.target);
  alert('存储数据完成');
};

transaction.onsuccess = function(event ) {
  console.log('onsuccess 事件');
}

}

function clear() {
// body…
let transaction = db.transaction(‘customers’, ‘readwrite’);
let store = transaction.objectStore(‘customers’).clear();
store.onerror = function(event) {
console.log(‘清空数据战败’);
}
store.onsuccess = function(event) {
console.log(‘清空数据成功’);
}
}

// 使用事务 直接通过已知的键索引 单个对象 (只可以索引单个对象)
function getData() {
let transaction = db.transaction(‘customers’, ‘readwrite’); //
创造二个东西, 并定义该业务的操作为 “readonly”
let store = transaction.objectStore(‘customers’).get(‘444-44-4444’); //
使用get() 可以得到值

store.onerror = function (event) {
  alert('did not get the object');
}

store.onsuccess = function (event) {
  var result = event.target.result;
  console.log(result);
  alert('获取数据完成! 年龄是: ' + result.age);
}

}

function deleteData() {
let transaction = db.transaction(‘customers’, ‘readwrite’);
let store = transaction.objectStore(‘customers’);
store.delete(‘444-44-4444’);
alert(‘s删除数据产生’);
}

// 在作行业内部创制游标查询 能够索引 多个对象(注意: 是多少个指标)
// 游标不提前手提式无线电话机结果
function cursorQuery() {
let transaction = db.transaction(‘customers’, ‘readwrite’),
store = transaction.objectStore(‘customers’),
request = store.openCursor(null) ; // 这里创办游标

request.onsuccess = function (event) {

  // event.target.result 中保存的是在存储空间中查询到的对象
  // event.target.result 中有几个属性值,可以了解到查询到的对象中的细节,
  // key: 当前访问的对象的键
  // value:当前访问的实际对象
  // primaryKey: 游标使用的键
  // direction:数值,表示游标移动的方向

  let cursor = event.target.result;
  let value, updateRequest, deleteRequest;
  if (cursor) {
  //   if (cursor.key === '555-55-5555') {
  //     value = cursor.value;   // 获取到实际的访问对象
  //     value.name = 'hexon';   // 修改对象的name属性

  //     updateRequest = cursor.update(value);      // 调用update()方法可以用指定的对象,更新对象的value
  //     updateRequest.onsuccess = function() {
  //       // 处理成功
  //     }
  //     updateRequest.onerror = function() {
  //       // 处理失败
  //     }


  //     // 使用游标删除当前项
  //     // deleteRequest = cursor.delete();
  //     // deleteRequest.onsuccess = function() {
  //     //   // 删除成功处理
  //     // }
  //     // deleteRequest.onerror = function() {
  //     //   // 删除失败处理
  //     // }


  //   }
  //   console.log(event.target.result);
  // }
  console.log(cursor.value);
  cursor.continue();      // 移动到下一项,
  }
  request.onerror = function(event) {
    console.log('游标查询创建失败')
  }
}

}

// 使用keyrange查询
function keyRangeQuery() {
let transaction = db.transaction(‘customers’, ‘readwrite’)
let store = transaction.objectStore(‘customers’);
// 使用bound()方法 定义键范围
let range = IDBKeyRange.bound(‘555-55-5555’, ‘777-77-7777’, true,
false);
// 将键传入游标创立
let request = store.openCursor(range);

request.onsuccess = function(event) {
  let cursor = event.target.result;
  if (cursor) {
    console.log('游标查询到的值' + JSON.stringify(cursor.value));
    cursor.continue()     // 移动到下一项
  }

}

request.onerror = function(event) {
  console.log("使用游标 + keyrange 查询失败")
}

}

// 使用索引
function useIndex() {
let store = db.transaction(‘customers’).objectStore(‘customers’),
index = store.index(‘name’);
request = index.openCursor();
request.onsuccess = function (event) {
let cursor = event.target.result;
if (cursor) {
console.log(cursor);
cursor.continue();
}
}
}

addBtn.addEventListener(‘click’, function(e) {
save();
}, false);

deleteBtn.addEventListener(‘click’, function(e) {
deleteData();
}, false);

queryBtn.addEventListener(‘click’, function(e) {
getData();
}, false);

cursorBtn.addEventListener(‘click’, function(e) {
cursorQuery();
}, false);

clearBtn.addEventListener(‘click’, function(e) {
clear();
}, false);

keyRange.addEventListener(‘click’, function(e) {
keyRangeQuery();
}),

indexBtn.addEventListener(‘click’, function(e) {
useIndex();
})

</script>

</body>
</html>

IndexedDB是不是合乎本人的应用程序?

现在最要害的标题:“IndexedDB是还是不是顺应作者的应用程序?“像过去一律,答案是一定的:“视情状而定。“首先当您打算在顾客端保存数据时,你会虚构HTML5地面存储。本地存储获得左近浏览器的支撑,有十三分轻巧使用的API。轻巧有其优势,但其缺点是爱莫能助支撑复杂的追寻计策,存款和储蓄大量的数据,并提供业务协助。

IndexedDB是一个数据库。所以,当您想为客商端做出决定,考虑你怎么着在服务端选拔贰个持久化介质的数据库。你恐怕会问自身某些题目来提携调整顾客端数据库是还是不是相符你的应用程序,包涵:

若是您对内部的其他难题回复了“是的”,很有非常的大大概,IndexedDB是你的应用程序的三个很好的候选。

使用IndexedDB

于今,你早已有机会熟知了一部分的完整概念,下一步是最初兑现基于IndexedDB的应用程序。第二个步骤必要统一IndexedDB在不一样浏览器的完成。您能够很轻松地充裕各样商家性子的抉择的自己斟酌,同临时间在window对象上把它们设置为官方对象同样的称号。上面包车型客车清单展现了window.indexedDB,window.IDBTransaction,window.IDBKeyRange的末段结出是如何都被更新,它们棉被服装置为对应的浏览器的特定达成。

JavaScript

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

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

近些日子,各个数据库相关的大局对象具有正确的版本,应用程序能够希图利用IndexedDB起首职业。

利用概述

在本教程中,您将学习如何创造二个应用IndexedDB存款和储蓄数据的模块化JavaScript应用程序。为了打探应用程序是何等专业的,参谋图4,它描述了职务应用程序处于空白状态。从那边你可认为列表加多新职分。图5显得了录入了多少个职务到系统的画面。图6出示怎么删除三个任务,图7显示了正在编辑职责时的应用程序。

图片 4

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

图片 5

图5:职责列表

图片 6

图6:删除任务

图片 7

图7:编辑职责
现行反革命您熟识的应用程序的效劳,下一步是开始为网址铺设基础。

铺设基础

其一例子从落到实处那样叁个模块起头,它承担从数据库读取数据,插入新的靶子,更新现成对象,删除单个对象和提供在二个object
store删除全部指标的选项。那些例子达成的代码是通用的数据访谈代码,您能够在任何object
store上应用。

其一模块是经过多个应声执行函数表明式(IIFE)完结,它采用对象字面量来提供协会。下边包车型地铁代码是模块的摘要,表达了它的中央构造。

JavaScript

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

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

用这么的组织,能够使这几个应用程序的具备逻辑封装在一个名叫app的单对象上。另外,数据库相关的代码在三个称为db的app子对象上。

其一模块的代码应用IIFE,通过传递window对象来担保模块的适龄限制。使用use
strict确定保障这几个函数的代码函数是依据(javascript严酷格局)严酷编写翻译准绳。db对象作为与数据库交互的有着函数的主要容器。最终,window对象检查app的实例是不是存在,要是存在,模块使用当前实例,假如空中楼阁,则创制多少个新指标。一旦app对象成功重返或创建,db对象附加到app对象。

本文的其他部分将代码增添到db对象内(在implementation
here会
商议),为应用程序提供一定于数据库的逻辑。由此,如你所见本文前面包车型地铁一些中定义的函数,想想父db对象活动,但全部其它作用都以db对象的成员。完整的数据库模块列表见清单2。

Implementing Database-Specific Code

对数据库的各样操作关联着二个先决条件,即有二个开荒的数据库。当数据库正在被张开时,通过检查数据库版本来剖断数据库是不是需求其它改换。上边包车型客车代码突显了模块怎么着追踪当前版本,object
store名、某成员(保存了假设数据库张开须要完结后的数据库当前实例)。

JavaScript

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

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

在此地,数据库张开央浼发生时,模块乞请版本1数据库。如若数据库荒诞不经,可能版本小于1,upgrade
needed事件在展开央求实现前触发。这一个模块棉被服装置为只利用三个object
store,所以名字间接定义在这里。最终,实例成员被创建,它用于保存一旦展开央求完毕后的数据库当前实例。

接下去的操作是贯彻upgrade
needed事件的事件管理程序。在此间,检查当前object
store的名字来决断央求的object store名是或不是存在,要是一纸空文,创制object
store。

JavaScript

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

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

在那一个事件管理程序里,通过事件参数e.target.result来访问数据库。当前的object
store名称的列表在_db.objectStoreName的字符串数组上。将来,倘若object
store海市蜃楼,它是经过传递object
store名称和store的键的定义(自增,关联到数码的ID成员)来成立。

模块的下三个功用是用来捕获错误,错误在模块差异的央求创立时冒泡。

JavaScript

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

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

在此处,errorHandler在三个警告框突显别的错误。这几个函数是假意保持简单,对开垦和睦,当你读书运用IndexedDB,您能够很轻松地观望其余不当(当她们爆发时)。当您计划在生育境遇使用那一个模块,您须要在那几个函数中达成部分错误管理代码来和您的应用程序的上下文打交道。

于今基础达成了,这一节的别的部分将演示怎样促成对数据库实践一定操作。第一个须要检查的函数是open函数。

JavaScript

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

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

open函数试图张开数据库,然后奉行回调函数,告知数据库成功开发方可计划利用。通过访谈window.indexedDB调用open函数来创造展开诉求。那么些函数接受你想张开的object
store的名称和您想行使的数据库版本号。

若果央求的实例可用,第一步要进行的职业是安装错误管理程序和提高函数。记住,当数据库被张开时,假诺脚本央求比浏览器里更加高版本的数据库(或然只要数据库不设有),进级函数运营。可是,借使央浼的数据库版本相配当前数据库版本同期未有不当,success事件触发。

万一全勤成功,张开数据库的实例能够从呼吁实例的result属性获得,那个实例也缓存到模块的实例属性。然后,onerror事件设置到模块的errorHandler,作为今后其他央浼的一无所长捕捉管理程序。最终,回调被推行来报告调用者,数据库已经开垦而且正确地配备,可以运用了。

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

JavaScript

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

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

在此地,getObjectStore接受mode参数,允许你决定store是以只读照旧读写形式央浼。对于那个函数,暗许mode是只读的。

每一个针对object
store的操作都是在贰个事物的上下文中推行的。事务乞请接受二个object
store名字的数组。这几个函数此番被铺排为只使用贰个object
store,不过借使您须要在事情中操作七个object store,你要求传递三个object
store的名字到数组中。事务函数的第贰个参数是一个格局。

若是事情必要可用,您就能够透过传递需求的object
store名字来调用objectStore函数以博得object
store实例的访谈权。这些模块的别样函数使用getObjectStore来博取object
store的访谈权。

下贰个落到实处的函数是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的一个可写实例。然后,检查数据对象的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值能保险转变来贰个整数,数据库被展开,叁个可写的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地图