深入解析HTML5中的IndexedDB索引数据库,html5indexeddb

前面贰个的数据库: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请参照他事他说加以考察完整文书档案

深切深入分析HTML5中的IndexedDB索引数据库,html5indexeddb

那篇作品首要介绍了深入深入剖判HTML5中的IndexedDB索引数据库,包括事务锁等底工效的相关应用示例,需求的爱人能够参见下

介绍 IndexedDB是HTML5 WEB数据库,允许HTML5
WEB应用在客商浏览器端存款和储蓄数据。对于使用来讲IndexedDB非常苍劲、有用,能够在客商端的chrome,IE,Firefox等WEB浏览器中积存大量数量,上面简介一下IndexedDB的基本概念。
 
什么是IndexedDB IndexedDB,HTML5新的数量存款和储蓄,能够在客商端存款和储蓄、操作数据,可以使利用加载地更快,更加好地响应。它差异于关系型数据库,具有数据表、记录。它影响着大家陈设和开创应用程序的点子。IndexedDB
创设有数据类型和回顾的JavaScript持久对象的object,各样object能够有目录,使其行之有效地询问和遍历整个集合。本文为你提供了怎么在Web应用程序中运用IndexedDB的真诚事例。
 
开始 我们须要在奉行前富含下眼前置代码

JavaScript
Code复制内容到剪贴板

  1. var indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;
      
  2.     
  3. //prefixes of window.IDB objects   
  4. var IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction || window.msIDBTransaction;
      
  5. var IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange || window.msIDBKeyRange
      
  6.     
  7. if (!indexedDB) {   
  8. alert(“Your browser doesn’t support a stable version of IndexedDB.”)
      
  9. }  

 
打开IndexedDB 在创立数据库在此以前,我们先是须求为数据库成立数量,即使我们好似下的客户信息:

JavaScript
Code复制内容到剪贴板

  1. var userData = [   
  2. { id: “1”, name: “Tapas”, age: 33, email: “[email protected]” },
      
  3. { id: “2”, name: “Bidulata”, age: 55, email: “[email protected]” }
      
  4. ];  

前段时间大家须求用open(卡塔尔(قطر‎方法展开我们的数据库:

JavaScript
Code复制内容到剪贴板

  1. var db;   
  2. var request = indexedDB.open(“databaseName”, 1);   
  3.     
  4. request.onerror = function(e) {   
  5. console.log(“error: “, e);   
  6. };   
  7.     
  8. request.onsuccess = function(e) {   
  9. db = request.result;   
  10. console.log(“success: “+ db);   
  11. };   
  12. request.onupgradeneeded = function(e) {   
  13.     
  14. }  

如上所示,大家曾经张开了名称为”databaseName”,钦赐版本号的数据库,open(卡塔尔(قطر‎方法有四个参数:
1.第一个参数是数据库名称,它会检查实验名为”databaseName”的数据库是还是不是已经存在,假若存在则张开它,不然创立新的数据库。
2.次之个参数是数据库的本子,用于客商更新数据库布局。
 
onSuccess处理 发出成功事件时“onSuccess”被触发,假诺具备成功的呼吁都在那管理,大家得以因而赋值给db变量保存央求的结果供今后使用。
 
onerror的管理程序 发出错误事件时“onerror”被触发,假使展开数据库的进度中诉讼失败。
 
Onupgradeneeded管理程序 风流倜傥经您想翻新数据库(创立,删除或改动数据库),那么你必得落实onupgradeneeded管理程序,使您能够在数据库中做其余改动。
在“onupgradeneeded”管理程序中是足以变动数据库的布局的并世无两地点。
 
成立和增进数据到表:
IndexedDB使用对象存款和储蓄来存款和储蓄数据,并非透过表。
每当三个值存款和储蓄在指标存款和储蓄中,它与一个键相关联。
它同意大家创设的任何对象存储索引。
索引允许我们访问存款和储蓄在对象存储中的值。
上边包车型地铁代码突显了什么样创立对象存储并插入预先筹算好的数量:

JavaScript
Code复制内容到剪贴板

  1. request.onupgradeneeded = function(event) {   
  2. var objectStore = event.target.result.createObjectStore(“users”, {keyPath: “id”});
      
  3. for (var i in userData) {   
  4. objectStore.add(userData[i]);    
  5. }   
  6. }  

我们利用createObjectStore()方法创制一个目的存款和储蓄。 此方法选用八个参数:

  • 储存的称号和参数对象。
    在这里边,我们有二个名称叫”users”的靶子存储,并定义了key帕特h,那是目的唯风流倜傥性的属性。
    在此处,我们应用“id”作为keyPath,这一个值在对象存款和储蓄中是唯朝气蓬勃的,大家亟须确定保证该“ID”的习性在对象存款和储蓄中的每种对象中留存。
    大器晚成旦创设了指标存款和储蓄,大家能够最初使用for循环增加数据进去。
     
    手动将数据增进到表:
    我们得以手动增加额外的数目到数据库中。

JavaScript
Code复制内容到剪贴板

  1. function Add() {   
  2. var request = db.transaction([“users”], “readwrite”).objectStore(“users”)
      
  3. .add({ id: “3”, name: “Gautam”, age: 30, email: “[email protected]” });
      
  4.     
  5. request.onsuccess = function(e) {   
  6. alert(“Gautam has been added to the database.”);   
  7. };   
  8.     
  9. request.onerror = function(e) {   
  10. alert(“Unable to add the information.”);    
  11. }   
  12.     
  13. }  

早前我们在数据库中做别的的CRUD操作(读,写,校勘),必需利用职业。
该transaction(卡塔尔国方法是用来内定我们想要实行事务管理的目的存款和储蓄。
transaction(卡塔尔国方法选用3个参数(第4个和第多少个是可选的)。
第叁个是大家要管理的对象存款和储蓄的列表,第一个内定大家是还是不是要只读/读写,第七个是本子变化。
 
从表中读取数据 get(卡塔尔(英语:State of Qatar)方法用于从指标存款和储蓄中搜寻数据。
我们事情发生前早就安装对象的id作为的keyPath,所以get(卡塔尔国方法将追寻具有相符id值的目的。
下边包车型地铁代码将回来大家命名称为“Bidulata”的靶子:

JavaScript
Code复制内容到剪贴板

  1. function Read() {   
  2. var objectStore = db.transaction([“users”]).objectStore(“users”);
      
  3. var request = objectStore.get(“2”);   
  4. request.onerror = function(event) {   
  5. alert(“Unable to retrieve data from database!”);   
  6. };   
  7. request.onsuccess = function(event) {    
  8. if(request.result) {   
  9. alert(“Name: ” + request.result.name + “, Age: ” + request.result.age + “, Email: ” + request.result.email);
      
  10. } else {   
  11. alert(“Bidulata couldn’t be found in your database!”);    
  12. }   
  13. };   
  14. }  

 
从表中读取全部数据
下边包车型客车议程寻觅表中的全部数据。
这里大家采纳游标来探求对象存款和储蓄中的全数数据:

JavaScript
Code复制内容到剪贴板

  1. function ReadAll() {   
  2. var objectStore = db.transaction(“users”).objectStore(“users”); 
      
  3. var req = objectStore.openCursor();   
  4. req.onsuccess = function(event) {   
  5. db.close();   
  6. var res = event.target.result;   
  7. if (res) {   
  8. alert(“Key ” + res.key + ” is ” + res.value.name + “, Age: ” + res.value.age + “, Email: ” + res.value.email);
      
  9. res.continue();   
  10. }   
  11. };   
  12. req.onerror = function (e) {   
  13. console.log(“Error Getting: “, e);   
  14. };    
  15. }  

该openCursor(卡塔尔(قطر‎用于遍历数据库中的五个记录。
在continue(卡塔尔(قطر‎函数中三番三次读取下一条记下。
删去表中的笔录 上边包车型客车不二等秘书技从指标中去除记录。

JavaScript
Code复制内容到剪贴板

  1. function Remove() {    
  2. var request = db.transaction([“users”], “readwrite”).objectStore(“users”).delete(“1”);
      
  3. request.onsuccess = function(event) {   
  4. alert(“Tapas’s entry has been removed from your database.”);   
  5. };   
  6. }  

大家要将指标的keyPath作为参数字传送递给delete(卡塔尔国方法。
 
终极代码
上面包车型地铁艺术从指标源中删除一条记下:

JavaScript
Code复制内容到剪贴板

  1. <!DOCTYPE html>  
  2. <head>  
  3. <meta http-equiv=”Content-Type” content=”text/html; charset=utf-8″ />  
  4. <title>IndexedDB</title>  
  5. <script type=”text/javascript”>  
  6. var indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;
      
  7.     
  8. //prefixes of window.IDB objects   
  9. var IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction || window.msIDBTransaction;
      
  10. var IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange || window.msIDBKeyRange
      
  11.     
  12. if (!indexedDB) {   
  13. alert(“Your browser doesn’t support a stable version of IndexedDB.”)
      
  14. }   
  15. var customerData = [   
  16. { id: “1”, name: “Tapas”, age: 33, email: “[email protected]” },
      
  17. { id: “2”, name: “Bidulata”, age: 55, email: “[email protected]” }
      
  18. ];   
  19. var db;   
  20. var request = indexedDB.open(“newDatabase”, 1);   
  21.     
  22. request.onerror = function(e) {   
  23. console.log(“error: “, e);   
  24. };   
  25.     
  26. request.onsuccess = function(e) {   
  27. db = request.result;   
  28. console.log(“success: “+ db);   
  29. };   
  30.     
  31. request.onupgradeneeded = function(event) {   
  32.     
  33. }   
  34. request.onupgradeneeded = function(event) {   
  35. var objectStore = event.target.result.createObjectStore(“users”, {keyPath: “id”});
      
  36. for (var i in userData) {   
  37. objectStore.add(userData[i]);    
  38. }   
  39. }   
  40. function Add() {   
  41. var request = db.transaction([“users”], “readwrite”)
      
  42. .objectStore(“users”)   
  43. .add({ id: “3”, name: “Gautam”, age: 30, email: “[email protected]” });
      
  44.     
  45. request.onsuccess = function(e) {   
  46. alert(“Gautam has been added to the database.”);   
  47. };   
  48.     
  49. request.onerror = function(e) {   
  50. alert(“Unable to add the information.”);    
  51. }   
  52.     
  53. }   
  54. function Read() {   
  55. var objectStore = db.transaction(“users”).objectStore(“users”);
      
  56. var request = objectStore.get(“2”);   
  57. request.onerror = function(event) {   
  58. alert(“Unable to retrieve data from database!”);   
  59. };   
  60. request.onsuccess = function(event) {    
  61. if(request.result) {   
  62. alert(“Name: ” + request.result.name + “, Age: ” + request.result.age + “, Email: ” + request.result.email);
      
  63. } else {   
  64. alert(“Bidulata couldn’t be found in your database!”);    
  65. }   
  66. };   
  67. }   
  68. function ReadAll() {   
  69. var objectStore = db.transaction(“users”).objectStore(“users”); 
      
  70. var req = objectStore.openCursor();   
  71. req.onsuccess = function(event) {   
  72. db.close();   
  73. var res = event.target.result;   
  74. if (res) {   
  75. alert(“Key ” + res.key + ” is ” + res.value.name + “, Age: ” + res.value.age + “, Email: ” + res.value.email);
      
  76. res.continue();   
  77. }   
  78. };   
  79. req.onerror = function (e) {   
  80. console.log(“Error Getting: “, e);   
  81. };    
  82. }   
  83. function Remove() {    
  84. var request = db.transaction([“users”], “readwrite”).objectStore(“users”).delete(“1”);
      
  85. request.onsuccess = function(event) {   
  86. alert(“Tapas’s entry has been removed from your database.”);   
  87. };   
  88. }   
  89. </script>  
  90. </head>  
  91.     
  92. <body>  
  93. <button onclick=”Add()”>Add record</button>  
  94. <button onclick=”Remove()”>Delete record</button>  
  95. <button onclick=”Read()”>Retrieve single record</button>  
  96. <button onclick=”ReadAll()”>Retrieve all records</button>  
  97. </body>  
  98. </html>  

localStorage是不带lock成效的。那么要促成前端的数量分享而且须要lock功效这就需求选取任何本积攒方式,比方indexedDB。indededDB使用的是事务处理的体制,那其实正是lock功效。
  做这几个测量试验要求先轻易的卷入下indexedDB的操作,因为indexedDB的连接比较辛苦,并且八个测验页面都亟待用到

JavaScript
Code复制内容到剪贴板

  1. //db.js   
  2. //封装事务操作   
  3. IDBDatabase.prototype.doTransaction=function(f){   
  4.   f(this.transaction([“Obj”],”readwrite”).objectStore(“Obj”));   
  5. };   
  6. //连接数据库,成功后调用main函数   
  7. (function(){   
  8.   //展开数据库   
  9.   var cn=indexedDB.open(“TestDB”,1);   
  10.   //成立数量对象   
  11.   cn.onupgradeneeded=function(e){   
  12.     e.target.result.createObjectStore(“Obj”);   
  13.   };   
  14.   //数据库连接成功   
  15.   cn.onsuccess=function(e){   
  16.     main(e.target.result);   
  17.   };   
  18. })();   
  19.   接着是四个测量试验页面   
  20. <script src=”db.js”></script>  
  21. <script>  
  22. //a.html   
  23. function main(e){   
  24.   (function callee(){   
  25.     //起首多少个事务   
  26.     e.doTransaction(function(e){   
  27.       e.put(1,”test”); //设置test的值为1   
  28.       e.put(2,”test”); //设置test的值为2   
  29.     });   
  30.     setTimeout(callee);   
  31.   })();   
  32. };   
  33. </script>  
  34. <script src=”db.js”></script>  
  35. <script>  
  36. //b.html   
  37. function main(e){   
  38.   (function callee(){   
  39.     //起初一个政工   
  40.     e.doTransaction(function(e){   
  41.       //获取test的值   
  42.       e.get(“test”).onsuccess=function(e){   
  43.         console.log(e.target.result);   
  44.       };   
  45.     });   
  46.     setTimeout(callee);   
  47.   })();   
  48. };   
  49. </script>  

把localStorage换到了indexedDB事务管理。但是结果就分化

图片 2

测验的时候b.html中大概不会即时有出口,因为indexedDB正忙着处理a.html东西,b.html事务丢在了业务丢队列中等待。不过无论怎样,输出结果也不会是1以此值。因为indexedDB的矮小管理单位是业务,实际不是localStorage那样以表明式为单位。那样只要把lock和unlock之间需求管理的东西放入四个事务中就可以达成。别的,浏览器对indexedDB的支持不及localStorage,所以采纳时还得寻思浏览器包容。

那篇随笔首要介绍了深深深入深入分析HTML5中的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值。

依照事务

不一致于一些金钱观的关周详据库的完结,每二个对数据库操作是在三个政工的内外文中实践的。事务约束贰回影响贰个或两个object
stores,你通过传播五个object store名字的数组到创立职业约束的函数来定义。

创建工作的第一个参数是专门的学问情势。当号令一个事务时,必得决定是遵循只读依然读写方式乞求访问。事务是能源密集型的,所以蓬蓬勃勃旦你无需改过data
store中的数据,你只需求以只读形式对object stores集结举办号召访问。

项目清单2示范了怎么选拔极度的形式创造贰个作业,并在这里片随笔的 Implementing
Database-Specific Code
 部分举行了详尽讨论。

基于央求

以至这里,有多少个一再现身的宗旨,您大概曾经注意到。对数据库的每一回操作,描述为经过贰个须要张开数据库,访谈多少个object
store,再持续。IndexedDB
API天生是依靠乞请的,那也是API异步特性提示。对于你在数据库推行的每趟操作,你必得首先为那一个操作创立二个呼吁。当倡议达成,你能够响应由乞请结果产生的事件和不当。

本文达成的代码,演示了如何利用央求展开数据库,创立八个事情,读取object
store的剧情,写入object store,清空object store。

开发数据库的央求生命周期

IndexedDB使用事件生命周期管理数据库的张开和安插操作。图2示范了二个开采的央浼在必然的条件下发生upgrade
need事件。

图片 3

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

持有与数据库的竞相以前于贰个开垦的哀求。试图展开数据库时,您必需传递一个被号召数据库的版本号的整数值。在开辟央浼时,浏览器比较你传入的用于打开央浼的版本号与实际数据库的版本号。纵然所央浼的版本号高于浏览器中当前的版本号(只怕今后还未存在的数据库卡塔尔(قطر‎,upgrade
needed事件触发。在uprade
need事件时期,你有时机通过丰硕或移除stores,键和索引来垄断(monopoly卡塔尔国object stores。

即使所央求的数据库版本号和浏览器的近日版本号雷同,可能晋级历程日试万言,三个展开的数据库将赶回给调用者。

荒诞冒泡

理所当然,一时候,央求大概不会按预想实现。IndexedDB
API通过荒诞冒泡效果来帮助追踪和管理不当。若是一个特定的呼吁境遇错误,你能够尝尝在伏乞对象上管理错误,大概你能够允许错误通过调用栈冒泡向上传递。这么些冒泡个性,使得你无需为各个诉求达成特定错误处理操作,而是能够接纳只在叁个越来越高等别上加多错误管理,它给您四个机会,保持您的错误管理代码简洁。本文中贯彻的例子,是在一个高端别管理错误,以便越来越细粒度操作产生的别的错误冒泡到通用的错误处理逻辑。

浏览器扶植

莫不在开荒Web应用程序最注重的难题是:“浏览器是还是不是接济本身想要做的?“固然浏览器对IndexedDB的支撑在继续提升,选取率并非大家所企望的那么广泛。图3体现了caniuse.com网站的告知,辅助IndexedDB的为66%多一小点。最新版本的银狐,Chrome,Opera,Safar,iOS
Safari,和Android完全扶持IndexedDB,Internet
Explorer和金立部分扶持。尽管那一个列表的维护者是欢腾的,但它未有报告全数传说。

图片 4

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

唯有可怜新本子的Safari和iOS Safari
扶植IndexedDB。据caniuse.com突显,这只占大致0.01%的大世界浏览器选取。IndexedDB不是多个你认为可以理当如此获得扶植的今世Web
API,可是你将快捷会这么以为。

另意气风发种接受

浏览器帮助本地数据库并非从IndexedDB才起来兑现,它是在WebSQL达成之后的意气风发种新章程。相近IndexedDB,WebSQL是贰个客商端数据库,但它看作三个关全面据库的得以达成,使用构造化查询语言(SQL卡塔尔与数据库通讯。WebSQL的野史充满了曲折,但底线是从未有过主流的浏览器厂家对WebSQL继续帮衬。

若果WebSQL实际上是三个摈弃的技艺,为何还要提它呢?有意思的是,WebSQL在浏览器里拿到稳步的支撑。Chrome,
Safari, iOS Safari, and
Android 浏览器都支持。其它,并非那一个浏览器的最新版本才提供扶植,超级多这个新型最佳的浏览器早前的本子也可以支撑。有意思的是,假如你为WebSQL增加帮衬来支撑IndexedDB,你乍然意识,好些个浏览器厂家和版本成为援救浏览器内置数据库的某种化身。

就此,假如你的应用程序真正要求一个客商端数据库,你想要达到的最高档其他采纳恐怕,当IndexedDB不可用时,大概你的应用程序可能看起来要求选拔选用WebSQL来辅助客户端数据结构。就算文书档案数据库和关周详据库管理数占领肯定的歧异,但假诺你有不利的抽象,就足以行使当地数据库创设一个应用程序。

IndexedDB是还是不是契合自己的应用程序?

现行反革命最珍视的标题:“IndexedDB是不是相符小编的应用程序?“像早先相通,答案是必然的:“视意况而定。“首先当你准备在顾客端保存数据时,你会杜撰HTML5地面存储。本地存储得到广大浏览器的支撑,有丰硕便于使用的API。轻松有其优势,但其劣点是无可奈何支撑复杂的查找计谋,存款和储蓄大量的数额,并提供职业扶持。

IndexedDB是八个数据库。所以,当你想为客商端做出决定,思考你什么在服务端选拔贰个漫长化介质媒质的数据库。你或者会问本人有个别标题来扶助调控客户端数据库是或不是顺应你的应用程序,富含:

  • 你的客户通过浏览器访问您的应用程序,(浏览器)协理IndexedDB API吗 ?
  • 您须要仓库储存大批量的数量在顾客端?
  • 您须要在二个巨型的多少集合中飞速牢固单个数根据地?
  • 您的结构在客商端必要专门的学问扶持吧?

设若您对中间的别样难题答问了“是的”,很有望,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呈现了正在编写制定任务时的应用程序。

图片 5

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

图片 6

图5:职分列表

图片 7

图6:删除职分

图片 8

图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的名字到数组中。事务函数的第3个参数是叁个形式。

纵然事情央求可用,您就足以因而传递要求的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卡塔尔(英语:State of Qatar)能够在清单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卡塔尔(英语:State of Qatar)临时叫做不一样的名字。有的时候能够看来那般的代码社团办法,它叫做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%20/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=”” target=”_blank”>Craig
Shoemaker</a> <a href=””
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

图片 9

博客园博客园:@hop_ping
个人主页 ·
小编的篇章 ·
17

图片 10

发表评论

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