HTML5中的新增功能indexedDB允许开发人员在Web浏览器中保留数据。 因此,您的应用程序可以通过强大的查询功能在线和离线运行。 indexedDB与传统的关系数据库的不同之处在于,它是一个objectStore
而不是行和列的集合。 您只需在indexedDB中创建一个objectStore
并将JavaScript对象存储在该存储中。 此外,对存储的对象执行CRUD操作非常容易。 本教程概述了indexedDB API,并说明了如何使用它来创建简单的记事本应用程序。
在开始之前,请注意indexedDB API规范尚未稳定。 但是,如果您在计算机上安装了最新的Firefox或Google Chrome浏览器,则可以使用。 要了解哪些浏览器版本支持API,请参阅兼容性表 。
indexedDB规范中有两种类型的API:同步和异步。 但是,我们将重点关注异步API,因为这是浏览器唯一支持的API。 异步意味着您对数据库执行操作,并通过DOM事件在回调中接收结果。
在任何笔记应用程序中,都有四个简单的功能:创建,读取,更新和删除。 indexedDB提供了非常简单的API来执行这些操作。 但是在做任何事情之前,我们需要创建一个数据库并打开它。
配置:
由于规范尚未稳定,因此不同的浏览器在其实现中使用前缀。 因此,您需要正确检查以确保浏览器支持indexedDB。 使用以下代码来确保浏览器支持indexedDB。
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; if (!window.indexedDB) { alert("Sorry!Your browser doesn't support IndexedDB"); }
打开/创建数据库:
打开indexedDB数据库只需调用indexedDB.open()
。
var request = window.indexedDB.open("notepad",1);
indexedDB.open()
接受两个参数。 第一个代表数据库名称。 如果数据库尚不存在,它将创建一个新数据库。 第二个参数是版本号。 如果将来需要更新数据库架构,则需要使用版本号高于前一个版本的版本号调用indexedDB.open()function
。 在这种情况下,您将需要实现onupgradeneeded
回调,您可以在其中更新数据库架构并创建/删除objectStores
。
创建数据库是第一步。 但是要存储某些东西,您需要有一个objectStore
。 创建数据库时,您可能还需要创建一个objectStore
。 最初创建数据库时,会触发onupgradeneeded
回调,您可以在其中创建objectStore
。
var database; var request = window.indexedDB.open("notepad",1); request.onerror = function(event) { console.log(event.target.errorCode); }; request.onsuccess = function(event) { database=request.result; }; request.onupgradeneeded = function(event) { var db = event.target.result; var objectStore = db.createObjectStore("notes", { keyPath: "id",autoIncrement:true}); };
在上面的代码示例中,我们使用数据库名称notepad和版本号1调用indexedDB.open()
。该方法返回IDBOpenDBRequest
。 数据库打开请求成功后,将触发request.onsuccess
回调。 request的result属性是IDBDatabase
的实例,我们将其分配给变量数据库以供以后使用。
在onupgradeneeded
回调中,我们获得了对数据库的引用,并使用它创建了一个名为notes
的新objectStore
。 createObjectStore()
函数还接受第二个参数。 在这种情况下,我们定义了一个名为id
的keyPath
,它唯一地标识商店中的对象。 另外,我们还希望id为autoIncrementing
。
在objectStore中添加/更新项目:
假设我们要在商店中保存笔记。 该对象应具有以下字段:标题,正文和创建日期。 要存储对象,请使用以下代码:
var note={title:”Test Note”, body:”Hello World!”, date:”01/04/2013”}; var transaction = database.transaction(["notes"], "readwrite"); var objectStore = transaction.objectStore("notes"); var request=objectStore.put(note); request.onsuccess = function(event) { //do something here };
database.transaction()
将数组作为第一个参数,该数组代表此事务跨度的objectStores
的名称。 第二个参数确定交易的类型。 如果您不传递第二个参数,则将获得只读事务。 由于我们要添加新项,因此将readwrite
作为第二个参数传递。 作为此调用的结果,我们获得了一个交易对象。 transaction.objectStore()
选择要操作的objectStore
。 最后, objectStore.put()
将对象添加到商店。 您还可以使用objectStore.add()
添加对象。 但是,如果我们尝试添加id
与现有条目的id
相同的新对象,则前者将更新商店中的对象。
从商店中删除商品:
从存储中删除对象非常简单明了。
var request = database.transaction(["notes"], "readwrite") .objectStore("notes").delete(20); request.onsuccess = function(event) { //handle success };
上面的代码从商店中删除了一个id
为20的对象。
查询存储中的所有对象:
对于任何数据库驱动的应用程序,通常会显示所有存储的条目。 在indexedDB中,您可以获取存储在存储中的对象,并在游标的帮助下对其进行遍历。
var objectStore = database.transaction("notes").objectStore("notes"); objectStore.openCursor().onsuccess = function(event) { var cursor = event.target.result; if (cursor) { alert("Note id: "+cursor.key+", Title: "+cursor.value.title); cursor.continue(); } };
上面的代码很容易理解。 openCursor()
函数可以接受多个参数。 您可以通过传递适当的参数来控制返回结果的范围和迭代的方向。 游标对象是请求的结果。 如果您期望多个对象并想要遍历它们,则应调用cursor.continue()
。 这意味着只要触发了cursor.continue()
,只要触发了onsuccess
回调的更多数据。
因此,这是在使用indexedDB开发记事本应用程序之前应了解的所有信息。 现在,我将逐步展示如何创建应用程序。
初始HTML标记:
<html> <head><title>Simple Notepad Using indexedDB</title> </head> <body> <div id="container"> <h3 id="heading">Add a note</h3> <input type="hidden" value="0" id="flag"/> <a href="#" id="add"><img src="add.png" οnclick="createNote(0)"/> New</a> <a href="#" id="back"><img src="back.png" οnclick="goBack()"/></a> <div id="notes"></div> <div id="editor" contenteditable="true"></div> </div> </body> </html>
说明:
我们有两个div:注释和编辑器。 第一个用于显示现有注释的列表,第二个用作编写注释的编辑器。 编辑器div最初是不可见的。 当用户单击添加按钮时,我们将隐藏笔记div并显示编辑器div。 您应该记住,通过设置contenteditable="true"
我们使div可编辑。 我们还有一个带有id标志的隐藏输入字段。 这将在本教程的后面部分中使用。
JavaScript:
<script type="text/javascript"> var database; 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; if (!window.indexedDB) { alert("Sorry!Your browser doesn't support IndexedDB"); } function init(){ var request = window.indexedDB.open("notepad",1); request.onerror = function(event) { console.log(event.target.errorCode); }; request.onsuccess = function(event) { database=request.result; showNotes(); }; request.onupgradeneeded = function(event) { var db = event.target.result; var objectStore = db.createObjectStore("notes", { keyPath: "id",autoIncrement:true}); }; } function createNote(id){ document.getElementById("editor").style.display="block"; document.getElementById("editor").focus(); document.getElementById("back").style.display="block"; document.getElementById("add").style.display="none"; document.getElementById("notes").style.display="none"; if(parseInt(id)!=0){ database.transaction("notes").objectStore("notes").get(parseInt(id)) .onsuccess = function(event) { document.getElementById("editor").innerHTML=event.target.result.body; document.getElementById("flag").value=id; }; } } function goBack(){ var note={}; note.body=document.getElementById("editor").innerHTML; note.title=getTitle(note.body); note.date=getDate(); var flag=parseInt(document.getElementById("flag").value); if(flag!=0) note.id=flag; if(note.title.trim()==="") window.location.href="index.html"; else addNote(note); } function getDate(){ var date=new Date(); var month=parseInt(date.getMonth())+1; return date.getDate()+"/"+month+"/"+date.getFullYear(); } function getTitle(body){ var body = body.replace(/(<([^>]+)>)/ig,""); if(body.length > 20) body = body.substring(0,20)+". . ."; return body; } function addNote(note){ var transaction = database.transaction(["notes"], "readwrite"); var objectStore = transaction.objectStore("notes"); var request=objectStore.put(note); request.onsuccess = function(event) { document.getElementById("flag").value="0"; window.location.href="index.html"; }; } function showNotes(){ var notes=""; var objectStore = database.transaction("notes").objectStore("notes"); objectStore.openCursor().onsuccess = function(event) { var cursor = event.target.result; if (cursor) { var link="<a class="notelist" id=""+cursor.key+"" href="#">"+cursor.value.title+"</a>"+" <img class="delete" src="delete.png" height="30px" id=""+cursor.key+""/>"; var listItem="<li>"+link+"</li>"; notes=notes+listItem; cursor.continue(); } else { document.getElementById("notes").innerHTML="<ul>"+notes+"</ul>"; registerEdit(); registerDelete(); } }; } function deleteNote(id){ var request = database.transaction(["notes"], "readwrite") .objectStore("notes") .delete(id); request.onsuccess = function(event) { window.location.href="index.html"; }; } function registerEdit(){ var elements = document.getElementsByClassName('notelist'); for(var i = 0, length = elements.length; i < length; i++) { elements[i].onclick = function (e) { createNote(this.id); } } } function registerDelete(){ var deleteButtons = document.getElementsByClassName('delete'); for(var i = 0, length = deleteButtons.length; i < length; i++){ deleteButtons[i].οnclick=function(e){ deleteNote(parseInt(this.id)); } } } window.addEventListener("DOMContentLoaded", init, false); </script>
说明:
init
方法执行必要的初始化。 它会创建/打开数据库,并在首次创建数据库时创建一个objectStore
。 成功打开数据库后,我们将获得对它的引用并将其存储在数据库变量中。
showNotes()
函数显示用户创建的注释列表。 我们开始交易并获取商店中存在的便笺对象。 然后,我们创建注释标题的无序列表,最后将其显示在具有id
注释的div中。 我们还调用了两个函数registerEdit()
和registerDelete()
。 第一个功能将单击事件侦听器附加到注释标题,注释标题是具有类注释列表的简单链接,以便当有人单击标题时可以编辑注释。 后一个功能将单击事件侦听器添加到注释标题旁边的删除按钮(简单图像)。 这样,当有人单击“删除”按钮时,我们可以删除注释。 deleteNote()
函数执行删除操作。
createNote()
函数显示一个编辑器,以创建新的笔记或更新现有的笔记。 它接受一个论点。 如果为0,则表示我们要创建一个新的音符。 否则,我们将开始交易以获取现有票据的内容。 我们将注释的id
传递给objectStore.get()
并在onsuccess
获取注释的主体。 然后,我们使用获取的注释主体填充编辑器。 另外,我们将隐藏的输入标志设置为goBack()
函数中使用的id。 当用户在写笔记后想返回时,将触发此方法。 我们将笔记保存在商店中。
在goBack()
函数中,我们创建一个新对象并设置其title,body和date属性。 标题是正文的前20个字符。 然后找出隐藏标志的值。 如果它不是0,我们知道我们要更新现有的音符。 因此,我们设置了创建对象的id
属性。 否则,不需要id
属性,因为该对象将成为商店中的新条目。 最后,以note对象作为参数调用addNote()
函数。 addNote()
函数只是启动一个事务,以添加/更新商店中的对象。 如果交易成功,我们会将用户带回他/她可以看到已创建笔记列表的地方。
您可以在此处试用演示应用程序。 我已经在Chrome 25和Firefox 20中测试了该应用程序。
indexedDB是HTML5中的出色API,与应用程序缓存一起使用时,其功能非常强大。 Mozilla提供了一些有关indexedDB的有趣且非常有用的信息。 如果您想了解更多,请检查一下。
如果您找不到任何东西,请在评论中告诉我。
From: https://www.sitepoint.com/creating-a-notepad-app-with-indexeddb/