菜单

前端的数据库:IndexedDB入门

2019年3月26日 - CSS/CSS3

IndexedDB是还是不是符合自身的应用程序?

近期最根本的标题:“IndexedDB是还是不是合乎小编的应用程序?“像往常一模一样,答案是一定的:“视意况而定。“首先当你打算在客户端保存数据时,你会考虑HTML5地面存款和储蓄。本地存款和储蓄得到周边浏览器的支撑,有那些不难使用的API。不难有其优势,但其劣势是心有余而力不足支撑复杂的追寻策略,存款和储蓄大批量的数目,并提供工作帮忙。

IndexedDB是四个数据库。所以,当你想为客户端做出决定,考虑你什么样在服务端选取贰个持久化介质的数据库。你恐怕会问本人有个别标题来救助控制客户端数据库是还是不是切合您的应用程序,包括:

假使您对里面包车型客车此外难题答疑了“是的”,很有只怕,IndexedDB是你的应用程序的三个很好的候选。

indexDB.open()艺术的原理

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

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

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

IndexedDB使用事件生命周期管理数据库的打开和配置操作。图2演示了1个开拓的请求在顺其自然的条件下发出upgrade
need事件。

图片 1

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

怀有与数据库的相互初步于二个打开的央求。试图打开数据库时,您必须传递1个被呼吁数据库的本子号的整数值。在开辟请求时,浏览器比较你传入的用来打开请求的版本号与实际数据库的版本号。假若所请求的版本号高于浏览器中当前的版本号(可能未来从未有过存在的数据库),upgrade
needed事件触发。在uprade
need事件之间,你有机会通过添加或移除stores,键和索引来操纵object stores。

一经所请求的数据库版本号和浏览器的脚下版本号一致,或然升级进程实现,八个开辟的数据库将回来给调用者。

使用办法

错误冒泡

理所当然,有时候,请求大概不会按预想实现。IndexedDB
API通过荒谬冒泡效果来协助跟踪和管制不当。假诺三个一定的伏乞蒙受错误,你能够品尝在乞请对象上处理错误,可能您能够允许错误通过调用栈冒泡向上传递。这些冒泡特性,使得你不须求为各类请求实现特定错误处理操作,而是能够选取只在五个更高级别上添加错误处理,它给您2个时机,保持你的错误处理代码简洁。本文中落实的例证,是在一个高级别处理错误,以便更细粒度操作发生的别的不当冒泡到通用的错误处理逻辑。

介绍

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

前者的数据库:IndexedDB入门

2014/12/27 · 未分类 · IndexedDB

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

应用程序需求多少。对一大半Web应用程序来说,数据在劳务器端组织和治本,客户端通过网络请求获取。随着浏览器变得进一步有能力,因而可挑选在浏览器存款和储蓄和决定应用程序数据。

正文向您介绍名为IndexedDB的浏览器端文书档案数据库。使用lndexedDB,你能够透过惯于在劳务器端数据库大致相同的法子创造、读取、更新和删除多量的笔录。请使用本文中可工作的代码版本去体验,完整的源代码能够因而GitHub库找到。

读到本课程的末段时,你将熟谙IndexedDB的基本概念以及怎么着落到实处3个运用IndexedDB执行总体的CRUD操作的模块化JavaScript应用程序。让我们有点亲近IndexedDB并发轫吧。

什么是IndexedDB

一般的话,有三种不一致类别的数据库:关系型和文书档案型(也叫做NoSQL或对象)。关周全据库如SQL
Server,MySQL,Oracle的数额存款和储蓄在表中。文书档案数据库如MongoDB,CouchDB,Redis将数据集作为个体对象存款和储蓄。IndexedDB是多个文书档案数据库,它在一齐内停放浏览器中的三个沙盒环境中(强制根据(浏览器)同源策略)。图1来得了IndexedDB的数额,呈现了数据库的构造

图片 2

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

整整的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事件处理程序中才能访问到数码

安顿指南

IndexedDB的架构很像在局地风靡的服务器端NOSQL数据库完结中的设计指南类型。面向对象数据通过object
stores(对象仓库)举行持久化,全部操作基于请求同时在工作限制内实行。事件生命周期使您可见决定数据库的配备,错误通过荒谬冒泡来使用API管理。

储存数据

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

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

听别人说请求

以至于那里,有一个反复出现的主旨,您只怕曾经注意到。对数据库的每一遍操作,描述为经过二个呼吁打开数据库,访问一个object
store,再持续。IndexedDB
API天生是基于请求的,那也是API异步天性提醒。对于你在数据库执行的每回操作,你不可能不首先为那一个操作创制3个请求。当呼吁完毕,你能够响应由请求结果产生的轩然大波和谬误。

正文完成的代码,演示了怎样利用请求打开数据库,创造叁个业务,读取object
store的内容,写入object store,清空object store。

选拔游标查询数据

行使工作能够一向通过
已知的键检索单个对象。而在急需摸索八个指标时,则要求在事情内创立游标。

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

如下:

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

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

地方例子中,能够行使cursor.delete()办法删除当前项

依照事务

分裂于一些观念的关周全据库的完成,每二个对数据库操作是在三个作业的内外文中执行的。事务限制贰遍影响三个或几个object
stores,你通过传播一个object store名字的数组到开创工作限制的函数来定义。

成立工作的第2个参数是工作情势。当呼吁1个事务时,必须决定是鲁人持竿只读照旧读写格局请求访问。事务是财富密集型的,所以假如你不要求更改data
store中的数据,你只需求以只读格局对object stores集合实行呼吁访问。

清单2演示了怎么运用相当的形式开创二个工作,并在那片小说的 Implementing
Database-Specific Code
 部分开始展览了详细钻探。

键范围

游标也还可以3个键,约等于通过键来设定游标查找的界定;
代码如下:

<!DOCTYPE html>
<html lang=”en”>
<head>
<meta charset=”UTF-8″>
<title>WebStorage DEMO</title>
</head>
<body>
<div class=”networkStatus”>
<button class=”clear”>清空数据</button>
<button class=”add”>添加数量</button>
<button class=”query”>查询数据</button>
<button class=”delete”>删除数据</button>
<button class=”cursor”>使用游标查询</button>
<button class=”keyRange”>使用keyrange查询</button>
<button class=”index”>使用index</button>
</div>

<script>
let network = document.querySelector(‘.networkStatus’),
addBtn = document.querySelector(‘.add’),
queryBtn = document.querySelector(‘.query’),
deleteBtn = document.querySelector(‘.delete’),
cursorBtn = document.querySelector(‘.cursor’),
clearBtn = document.querySelector(‘.clear’),
keyRange = document.querySelector(‘.keyRange’),
indexBtn = document.querySelector(‘.index’)
;

// 判断网路是或不是在线
// if (navigator.onLine) {
// network.innerText = “网络在线”;
// } else {
// network.innerText = “互联网掉线”;
// }

// // 监察和控制网络状态的事件:online 和 offline, 那多少个事件在window对象上
// window.addEventListener(‘online’, () => {
// network.innerText = “网络在线”;
// });

// window.addEventListener(‘offline’, () => {
// network.innerText = “网络掉线”;
// });

//——–cookie的使用—————
let CookieUtil = {
get: (name) => {
let cookieName = encodeURIComponent(name) + “=”,
cookieStart = document.cookie.indexOf(cookieName),
cookieValue = null;

  if (cookieStart > -1) {
    let cookieEnd = document.cookie.indexOf(';', cookieStart);
    if (cookieEnd === -1) {
      cookieEnd = document.cookie.length;
    }
    cookieValue = decodeURIComponent(document.cookie.substring(cookieStart + cookieName.length, cookieEnd));
  }

  return cookieValue;
},
set: function (name, value, expires, path, domain, secure) {
  let cookieText = encodeURIComponent(name) + '=' +
                   encodeURIComponent(value);

  if (expires instanceof Date) {
    cookieText += '; expires=' + expires.toGMTString();
  }

  if (path) {
    cookieText += '; path=' + path;
  }

  if (domain) {
    cookieText += '; domain=' + domain;
  }

  if (secure) {
    cookieText += '; secure';
  }

  document.cookie = cookieText;
},

// 删除cookie, 并没有直接的删除cookie的方法,这里通过重新设置cookie名称,来对cookie进行替换
// 同时 将过期时间expires设置为过去的时间,
unset: function(name, path, domain, secure) {
  this.set(name, '', new Date(0), path, domain, secure);
}

}

CookieUtil.set(‘name’, ‘hexon’);
CookieUtil.set(‘book’, ‘Profession Javascript’);

// 读取cookie的值
// console.log(CookieUtil.get(‘name’));
// console.log(CookieUtil.get(‘book’));

// 删除cookie
CookieUtil.unset(‘name’);
CookieUtil.unset(‘book’);

// 设置cookie, 蕴涵它的门道、域、失效日期
CookieUtil.set(‘name’, ‘Hexon’, ‘books/projs/’,
www.wrox.com’, new
Date(‘January 1, 2017’));

// 删除刚刚安装的cookie
CookieUtil.unset(‘name’, ‘books/projs/’,
www.www.wrox.com’);

// 设置安全的cookie
CookieUtil.unset(‘name’, ‘hexon’, null, null, null, null, true)

// — IndexedDB 数据库的应用
var request = window.indexedDB.open(‘dbName’, 2)
var db;
const dbName = ‘the_name’;
// 创造2个数额
const customerData = [
{ ssn: ‘444-44-4444’, name: ‘AAA’, age: 35, email:
AAA@company.com‘},
{ ssn: ‘666-66-6666’, name: ‘CCC’, age: 35, email:
CCC@company.com‘},
{ ssn: ‘777-77-7777’, name: ‘DDD’, age: 32, email:
DDD@home.org‘},
{ ssn: ‘555-55-5555’, name: ‘BBB’, age: 32, email:
BBB@home.org‘},

];

window.indexedDB = window.indexedDB || window.msIndexedDB ||
window.mozIndexedDB || window.webkitIndexedDB;
window.IDBTransaction = window.IDBTransaction ||
window.webkitIDBTransaction || window.msIDBTransaction || {READ_WRITE:
“readwrite”};
window.IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange ||
window.msIDBKeyRange;
window.IDBCursor = window.IDBCursor || window.webkitIDBTransaction;

if (!window.indexedDB) {
window.alert(“Your browser doesn’t support a stable version of
IndexedDB.”)
}

// 3
是建立的数据库版本,假若名为MyTestDatabase的数据库不设有,就会成立该数据库,然后
onupgradeneeded 事件会被触发;
// 即使数据仓库储存在,可是对版本升级了,也会触发onupgradeneeded事件,
// 注意:版本号是一个 unsigned long long
类型的值,由此不要使用float,不然会将其更换为其最接近的平头

// 生成处理程序
request.onerror = function (event) {
// do Something
alert(‘Database error: ‘ + event.target.errorCode);
};

request.onsuccess = function (event) {
// do Something
console.log(‘创立数据库成功’);
db = event.target.result; // 创制成功后,e.target.result
中蕴藏的是IDBDatabase对象的实例
}

// 当创制三个新的数目库 或许 更新已存在数据库的版本,
onupgradeneeded事件将会被触发,新的靶子存款和储蓄在event.target.result中。
//
在该处理程序中,数据库已经拥有先前版本的对象存款和储蓄,因而不要再一次成立那些指标存款和储蓄,只必要创立任何大家供给的靶子存储,大概
//
从从前版本中删去不在必要的目的存款和储蓄。如若急需转移当前指标存款和储蓄,则必须先删除旧的对象存款和储蓄,然后在利用新的选项成立。
// 删除旧的指标存储,在其上的音讯都会被删去;
//
注意:该事件是唯一三个能够对数据库举办操作的地方,在该事件之中,你对指标存款和储蓄实行删除、修改或移除索引
request.onupgradeneeded = function(event) {
console.log(‘onupgradeneeded’);
var db = event.target.result;

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

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

}

function save(data) {
///
对于数据库的靶子存储空间中数据的读取或修改数据,都要经过事物来组织全体操作
// 最简易的开创事物的艺术是:var transaction = db.transaction();
let transaction = db.transaction(‘customers’, ‘readwrite’); //
创造二个政工,并定义该事务的操作为 “readwrite” ,并赶回其索引
let store = transaction.objectStore(‘customers’); //
取得索引后,使用objectStore()方法并传到存款和储蓄空间的名称,就能够访问特定的仓库储存空间

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

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

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

}

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

// 使用事务 直接通过已知的键索引 单个对象 (只好索引单个对象)
function getData() {
let transaction = db.transaction(‘customers’, ‘readwrite’); //
成立3个事物, 并定义该工作的操作为 “readonly”
let store = transaction.objectStore(‘customers’).get(‘444-44-4444’); //
使用get() 能够得到值

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

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

}

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

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

request.onsuccess = function (event) {

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

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

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


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


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

}

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

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

}

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

}

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

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

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

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

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

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

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

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

</script>

</body>
</html>

采纳概述

在本教程中,您将学习怎么样创设一个用到IndexedDB存款和储蓄数据的模块化JavaScript应用程序。为了打探应用程序是怎么着工作的,参考图4,它描述了任务应用程序处于空白状态。从这里你能够为列表添加新职务。图5显得了录入了多少个任务到系统的镜头。图6来得怎么删除一个职责,图7展现了正在编写制定任务时的应用程序。

图片 3

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

图片 4

图5:职责列表

图片 5

图6:删除职务

图片 6

图7:编辑职务
现行你纯熟的应用程序的效应,下一步是从头为网站铺设基础。

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才早先兑现,它是在WebSQL完毕之后的一种新形式。类似IndexedDB,WebSQL是二个客户端数据库,但它当做多个关周到据库的贯彻,使用结构化查询语言(SQL)与数据库通讯。WebSQL的野史充满了波折,但底线是从未有过主流的浏览器厂商对WebSQL继续补助。

一经WebSQL实际上是2个舍弃的技术,为啥还要提它吧?有趣的是,WebSQL在浏览器里获得巩固的支撑。Chrome,
Safari, iOS Safari, and
Android 浏览器都支持。此外,并不是这个浏览器的时髦版本才提供支撑,许多那个新颖最棒的浏览器在此之前的版本也得以匡助。有趣的是,假如您为WebSQL添加协助来支撑IndexedDB,你突然发现,许多浏览器厂商和版本成为支撑浏览器内置数据库的某种化身。

故而,如若你的应用程序真正必要3个客户端数据库,你想要达到的最高级别的运用或许,当IndexedDB不可用时,也许你的应用程序恐怕看起来要求选拔选用WebSQL来支撑客户端数据架构。就算文书档案数据库和关周密据库管理数据有拨云见日的异样,但要是您有科学的肤浅,就能够利用当地数据库创设一个应用程序。

连日数据库

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

对象仓库

object
store是IndexedDB数据库的基础。假若你选取过关周详据库,平常可以将object
store等价于2个数额库表。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值。

浏览器帮忙

兴许在开发Web应用程序最主要的题材是:“浏览器是或不是帮忙笔者想要做的?“固然浏览器对IndexedDB的辅助在此起彼伏增进,采取率并不是大家所梦想的那样普遍。图3展现了caniuse.com网站的告知,帮助IndexedDB的为66%多一丝丝。最新版本的银狐,Chrome,Opera,Safar,iOS
Safari,和Android完全帮助IndexedDB,Internet
Explorer和Motorola部分协助。即便这些列表的跟随者是动人心魄的,但它没有报告全体旧事。

图片 7

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

除非足够新本子的Safari和iOS Safari
帮助IndexedDB。据caniuse.com突显,这只占大约0.01%的全世界浏览器选择。IndexedDB不是三个您认为能够理所当然获得帮助的当代Web
API,可是你将高速会如此认为。

使用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开始工作。

执行用户界面特定代码

今昔享有特定于数据库的代码被封装在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

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的操作都以在3个事物的左右文中执行的。事务请求接受1个object
store名字的数组。那个函数本次被布署为只利用多少个object
store,但是假使您要求在事情中操作多少个object store,你须要传递多少个object
store的名字到数组中。事务函数的第四个参数是三个情势。

借使事情请求可用,您就可以透过传递需求的object
store名字来调用objectStore函数以赢得object
store实例的访问权。那么些模块的别的函数使用getObjectStore来博取object
store的访问权。

下一个完结的函数是save函数,执行插入或更新操作,它依照传入的数额是不是有3个ID值。

JavaScript

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

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

save函数的七个参数分别是亟需保留的多少对象实例和操作成功后需求实施的回调。读写方式用于将数据写入数据库,它被盛传到getObjectStore来取得object
store的三个可写实例。然后,检查数据对象的ID成员是还是不是留存。假如存在ID值,数据必须立异,put函数被调用,它创造持久化请求。否则,固然ID不设有,那是新数据,add请求再次回到。最后,不管put也许add
请求是还是不是进行了,success事件处理程序要求设置在回调函数上,来告诉调用脚本,一切进展顺遂。

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

在store访问数据时,游标遍历数据库中的每条记下,会触发onsuccess事件处理程序。当每条记下走访时,store的多寡能够透过e.target.result事件参数得到。就算事实上数目从target.result的value属性中拿走,首先需求在准备访问value属性前确定保证result是二个一蹴而就的值。要是result存在,您能够添加result的值到数据数组,然后在result对象上调用continue函数来三番五次迭代object
store。最后,若是没有reuslt了,对store数据的迭代截至,同时数据传递到回调,回调被执行。

现行反革命模块可以从data
store拿到全数数据,下三个亟需落成的函数是负责访问单个记录。

JavaScript

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

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

get函数执行的首先步操作是将id参数的值转换为一个整数。取决于函数被调用时,字符串或整数都可能传递给函数。这几个完毕跳过了对如若所给的字符串不能够转换成整数该怎么办的情形的拍卖。一旦一个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值被调用。当呼吁成功时,将履行回调函数。

在好几情形下,您或者供给删除1个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的2个可写实例。一旦store可用,3个新的呼吁通过调用clear函数来创制。一旦clear操作成功,回调函数被实施。

铺设基础

那些事例从落实如此1个模块开端,它承担从数据库读取数据,插入新的对象,更新现有对象,删除单个对象和提供在多少个object
store删除全数目的的选项。这几个事例完成的代码是通用的数量访问代码,您能够在任何object
store上应用。

其一模块是透过二个立即实施函数表明式(IIFE)实现,它应用对象字面量来提供组织。上边包车型客车代码是模块的摘要,表明了它的主干协会。

JavaScript

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

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

用如此的构造,能够使那么些应用程序的有着逻辑封装在3个名为app的单对象上。别的,数据库相关的代码在一个名为db的app子对象上。

其一模块的代码应用IIFE,通过传递window对象来确认保障模块的安妥限制。使用use
strict确定保障那一个函数的代码函数是比照(javascript严苛情势)严苛编写翻译规则。db对象作为与数据库交互的有着函数的主要容器。最终,window对象检查app的实例是或不是存在,假诺存在,模块使用当前实例,假使不存在,则开创二个新对象。一旦app对象成功再次来到或创立,db对象附加到app对象。

正文的别的部分将代码添加到db对象内(在implementation
here会
评说),为应用程序提供一定于数据库的逻辑。因而,如你所见本文前面包车型地铁局地中定义的函数,想想父db对象活动,但全体别的效用都以db对象的分子。完整的数据库模块列表见清单2。

相关文章

发表评论

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

网站地图xml地图