摘要:對象應(yīng)該主要用于僅針對會話的小段數(shù)據(jù)的存儲。如下代碼限制與其它客戶端數(shù)據(jù)存儲方案類似,同樣也有限制。最好一開始就調(diào)用方法為數(shù)據(jù)庫指定一個版本號傳入一個表示版本號的字符串。目前就瀏覽器,版本號方法已不再適用,另外,創(chuàng)建
Cookie 限制
由于瀏覽器存在各種限制,最好將整個cookie長度限制在4095B以內(nèi)。
構(gòu)成cookie由瀏覽器保存的以下幾塊信息構(gòu)成:
名稱: cookie的名稱必須是經(jīng)過URL編碼后的字符串。 雖然它是不區(qū)分大小寫的, 但是實際應(yīng)用時建議把它當(dāng)作區(qū)分大小寫來使用。
值: cookie中字符串值, 也必須是經(jīng)過URI編碼的字符串。
域: 表示cookie對于哪個域有效。
路徑: cookie是針對域中的哪個目錄生效。
失效時間: 表示cookie失效時間的時間戳, 它是GMT格式的日期。 將該事件設(shè)置小于當(dāng)前時, 就相當(dāng)于刪除了cookie。
安全標(biāo)識: 指定該標(biāo)識后, 只有使用SSL請求連接的時候cookie才會發(fā)送到服務(wù)器。 secure標(biāo)識是cookie中唯一一個非鍵值對的部分, 它只包含一個secure單詞。
使用分號加空格分開各個信息構(gòu)成:
HTTP/1.1 200 OK Content-type: text/html Set-Cookie: CookieName=CookieValue; expires=Mon, 22-Jan-07 07:10:24 GMT; domain=.wrox.com Other-header: other-header-value
或使用安全標(biāo)志:
HTTP/1.1 200 OK Content-type: text/html Set-Cookie: CookieName=CookieValue; expires=Mon, 22-Jan-07 07:10:24 GMT; domain=.wrox.com; path=/; secure //在這里! Other-header: other-header-valueJavaScript中的Cookie
在JavaScript中可以通過
document.cookie可以讀取當(dāng)前域名下的cookie, 是用分號隔開的鍵值對構(gòu)成的字符串。 類似于name = aa;
age = 15;
注意所有的鍵值對名稱和值都是經(jīng)過encodeURIComponent() 編碼的, 使用時要進(jìn)行解碼。
當(dāng)給document.cookie賦值時, 不會直接覆蓋現(xiàn)有的cookie, 而是會追加一個新的cookie。 例如:
document.cookie = "a=1"; //執(zhí)行后會看到新增了一個cookie。
如:
document.cookie = encodeURIComponent("name") + "=" + encodeURIComponent("Oliver"); console.log(document.cookie); //name=Oliver;
如果給cookie賦值則會增加一個cookie:
document.cookie = encodeURIComponent("name") + "=" + encodeURIComponent("Oliver"); document.cookie = encodeURIComponent("age") + "=" + encodeURIComponent("18"); console.log(document.cookie); //name=Oliver; age=18
以下函數(shù)是常用的cookie讀寫刪除方法:
var CookieUtil = { //根據(jù)key讀取cookie get: function(name) { //注意對鍵編碼 var cookieName = encodeURIComponent(name) + "=", cookieStart = document.cookie.indexOf(cookieName), cookieValue = null, cookieEnd; //找到cookie鍵 if (cookieStart > -1) { //鍵后面第一個分號位置 cookieEnd = document.cookie.indexOf(";", cookieStart); if (cookieEnd == -1) { cookieEnd = document.cookie.length; } //cookie值解碼 cookieValue = decodeURIComponent(document.cookie.substring(cookieStart + cookieName.length, cookieEnd)); } return cookieValue; }, //設(shè)置cookie set: function(name, value, expires, path, domain, secure) { var cookieText = encodeURIComponent(name) + "=" + encodeURIComponent(value); //失效時間,GMT時間格式 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,保持相同的鍵、域、路徑、安全選項,然后設(shè)置失效時間即可 unset: function(name, path, domain, secure) { this.set(name, "", new Date(0), path, domain, secure); } };
可以像下面這樣使用上述方法:
設(shè)置cookie:
CookieUtil.set("name","Oliver"); CookieUtil.set("age","18"); console.log(document.cookie); //name=Oliver; age=18
讀取cookie的值:
console.log(CookieUtil.get("name")); //Oliver
刪除cookie:
CookieUtil.unset("name"); // console.log(document.cookie); //age=18
設(shè)置cookie路徑、域等:
CookieUtil.set("name","Oliver","/","localhost",null,false);
否則使用下面的代碼創(chuàng)建和刪除cookie:
//新cookie document.cookie = encodeURIComponent("name") + "=" + encodeURIComponent("Oliver"); //刪除上面創(chuàng)建的cookie document.cookie = encodeURIComponent("name") + "=" + encodeURIComponent("Oliver") + "; expires=" + new Date(0);
舉例
css:
DOM:
welcome to my site!
關(guān)閉
js:
子Cookie
由于瀏覽器cookie數(shù)量是有限制的,為了減少cookie數(shù)量可以使用子cookie的方式。在一個cookie值中使用類似查詢字符串的格式可以存儲多組鍵值對,這樣就不必每個鍵值對都占用一個cookie了。子cookie值舉例:
name=name1=value1&name2=value2獲取所有子cookie
獲取所有子cookie并將它放在一個對象中返回,對象的屬性名為子cookie名稱,對象的屬性值為子cookie的值。
getAll: function(name) { var cookieName = encodeURIComponent(name) + "=", cookieStart = document.cookie.indexOf(cookieName), cookieValue = null, cookieEnd, subCookies, i, parts, result = {}; if (cookieStart > -1) { cookieEnd = document.cookie.indexOf(";", cookieStart) if (cookieEnd == -1) { cookieEnd = document.cookie.length; } //取出cookie字符串值 cookieValue = document.cookie.substring(cookieStart + cookieName.length, cookieEnd); if (cookieValue.length > 0) { //用&將cookie值分隔成數(shù)組 subCookies = cookieValue.split("&"); for (i = 0, len = subCookies.length; i < len; i++) { //等號分隔出鍵值對 parts = subCookies[i].split("="); //將解碼后的兼職對分別作為屬性名稱和屬性值賦給對象 result[decodeURIComponent(parts[0])] = decodeURIComponent(parts[1]); } return result; } } return null; }獲取單個子cookie
get()獲取單個子cookie。
get: function(name, subName) { //獲取所有子cookie var subCookies = this.getAll(name); if (subCookies) { //從屬性中獲取單個子cookie return subCookies[subName]; } else { return null; } }設(shè)置整個cookie
setAll設(shè)置整個cookie
setAll: function(name, subcookies, expires, path, domain, secure) { var cookieText = encodeURIComponent(name) + "=", subcookieParts = new Array(), subName; //遍歷子cookie對象的屬性 for (subName in subcookies) { //要先檢測屬性名 if (subName.length > 0 && subcookies.hasOwnProperty(subName)) { //屬性名和屬性值編碼后=連接為字符串,并放到數(shù)組中 subcookieParts.push(encodeURIComponent(subName) + "=" + encodeURIComponent(subcookies[subName])); } } if (subcookieParts.length > 0) { //用&連接子cookie串 cookieText += subcookieParts.join("&"); if (expires instanceof Date) { cookieText += "; expires=" + expires.toGMTString(); } if (path) { cookieText += "; path=" + path; } if (domain) { cookieText += "; domain=" + domain; } if (secure) { cookieText += "; secure"; } } else { cookieText += "; expires=" + (new Date(0)).toGMTString(); } //設(shè)置整個cookie document.cookie = cookieText; }設(shè)置單個子cookie
set設(shè)置單個子cookie
set: function(name, subName, value, expires, path, domain, secure) { //獲取當(dāng)前cookie對象 var subcookies = this.getAll(name) || {}; //單個cookie對應(yīng)的屬性替換 subcookies[subName] = value; //重新設(shè)置cookie this.setAll(name, subcookies, expires, path, domain, secure); }刪除cookie
刪除整個cookie, 將失效時間設(shè)置為過期日期即可。
unsetAll: function(name, path, domain, secure) { this.setAll(name, null, new Date(0), path, domain, secure); }刪除單個子cookie
刪除單個子cookie,需要先獲取所有子cookie對象,然后刪除子cookie對應(yīng)的屬性,最后再將子cookie對象重新設(shè)置回去。
unset: function(name, subName, path, domain, secure) { //獲取當(dāng)前cookie對象 var subcookies = this.getAll(name); if (subcookies) { //刪除子cookie對應(yīng)的屬性 delete subcookies[subName]; //重新設(shè)置cookie this.setAll(name, subcookies, null, path, domain, secure); } }以下函數(shù)是常用的子cookie讀寫刪除方法:
var SubCookieUtil = { getAll: function(name) { var cookieName = encodeURIComponent(name) + "=", cookieStart = document.cookie.indexOf(cookieName), cookieValue = null, cookieEnd, subCookies, i, parts, result = {}; if (cookieStart > -1) { cookieEnd = document.cookie.indexOf(";", cookieStart) if (cookieEnd == -1) { cookieEnd = document.cookie.length; } //取出cookie字符串值 cookieValue = document.cookie.substring(cookieStart + cookieName.length, cookieEnd); if (cookieValue.length > 0) { //用&將cookie值分隔成數(shù)組 subCookies = cookieValue.split("&"); for (i = 0, len = subCookies.length; i < len; i++) { //等號分隔出鍵值對 parts = subCookies[i].split("="); //將解碼后的兼職對分別作為屬性名稱和屬性值賦給對象 result[decodeURIComponent(parts[0])] = decodeURIComponent(parts[1]); } return result; } } return null; }, get: function(name, subName) { //獲取所有子cookie var subCookies = this.getAll(name); if (subCookies) { //從屬性中獲取單個子cookie return subCookies[subName]; } else { return null; } }, setAll: function(name, subcookies, expires, path, domain, secure) { var cookieText = encodeURIComponent(name) + "=", subcookieParts = new Array(), subName; //遍歷子cookie對象的屬性 for (subName in subcookies) { //要先檢測屬性名 if (subName.length > 0 && subcookies.hasOwnProperty(subName)) { //屬性名和屬性值編碼后=連接為字符串,并放到數(shù)組中 subcookieParts.push(encodeURIComponent(subName) + "=" + encodeURIComponent(subcookies[subName])); } } if (subcookieParts.length > 0) { //用&連接子cookie串 cookieText += subcookieParts.join("&"); if (expires instanceof Date) { cookieText += "; expires=" + expires.toGMTString(); } if (path) { cookieText += "; path=" + path; } if (domain) { cookieText += "; domain=" + domain; } if (secure) { cookieText += "; secure"; } } else { cookieText += "; expires=" + (new Date(0)).toGMTString(); } //設(shè)置整個cookie document.cookie = cookieText; }, set: function(name, subName, value, expires, path, domain, secure) { //獲取當(dāng)前cookie對象 var subcookies = this.getAll(name) || {}; //單個cookie對應(yīng)的屬性替換 subcookies[subName] = value; //重新設(shè)置cookie this.setAll(name, subcookies, expires, path, domain, secure); }, unsetAll: function(name, path, domain, secure) { this.setAll(name, null, new Date(0), path, domain, secure); }, unset: function(name, subName, path, domain, secure) { //獲取當(dāng)前cookie對象 var subcookies = this.getAll(name); if (subcookies) { //刪除子cookie對應(yīng)的屬性 delete subcookies[subName]; //重新設(shè)置cookie this.setAll(name, subcookies, null, path, domain, secure); } } };
舉例:
獲取cookie:
//若cookie為document.cookie=data=name=Oliver&book=jsbook; document.cookie = "data" + "=" + "name" + "=" + "Oliver" + "&" + "book" + "=" + "jsbook"; //取得全部子cookie var data = SubCookieUtil.getAll("data"); console.log(data.name); //Oliver console.log(data.book); //jsbook //獲取單個子cookie data = SubCookieUtil.get("data", "name"); console.log(data); //Oliver console.log(document.cookie); //data=name=Oliver&book=jsbook
設(shè)置cookie:
//若cookie為document.cookie=data=name=Oliver&book=jsbook; document.cookie = "data" + "=" + "name" + "=" + "Oliver" + "&" + "book" + "=" + "jsbook"; //設(shè)置兩個cookie SubCookieUtil.set("data", "name", "Nicholas"); SubCookieUtil.set("data", "book", "HTMLreference") console.log(document.cookie); //data=name=Nicholas&book=HTMLreference //設(shè)置全部子cookie SubCookieUtil.setAll("data", { name: "Troy", book: "JSON"}); console.log(document.cookie); //data=name=Troy&book=JSON //修改部分子cookie SubCookieUtil.set("data", "name", "Oli"); console.log(document.cookie); //data=name=Oli&book=JSON
刪除cookie:
//若cookie為document.cookie=data=name=Oliver&book=jsbook; document.cookie = "data" + "=" + "name" + "=" + "Oliver" + "&" + "book" + "=" + "jsbook"; //刪除部分子cookie SubCookieUtil.unset("data", "name"); console.log(document.cookie); //data=book=jsbook //刪除全部cookie SubCookieUtil.unsetAll("data"); console.log(document.cookie); //[This site has nos.]
舉例:
多個提醒banner的“不再提醒功能”存在同一個cookie中
css部分:
{
margin: 0; padding: 0;
}
div#message {
border: 1px solid #ccc; background-color: #33CCFF; margin: 0;
}
p.content {
color: white; font-size: 2em; margin: 0.3em; font-family: monospace; display: block;
}
a.notShow {
width: 2em; display: block; float: right;
}
dom部分:
js部分:
//獲取元素 var notShowBtn = document.getElementsByClassName("notShow"); //點擊關(guān)閉按鈕新建cookie并關(guān)閉banner var notShowBtnList = []; var hiddenElementCount = 0; for (var i = 0, len = notShowBtn.length; i < len; i++) { notShowBtnList.push(i); }; notShowBtnList.forEach(function(element, index) { notShowBtn[element].onclick = function() { event.preventDefault(); var value = "content" + element; SubCookieUtil.set("hideMessage", value, "hide"); notShowBtn[element].parentNode.style.display = "none"; }; }); //檢查cookie當(dāng)存在則關(guān)閉banner window.onload = function() { notShowBtnList.forEach(function(element, index) { var value = "content" + element; if (SubCookieUtil.get("hideMessage", value)) { notShowBtn[element].parentNode.style.display = "none"; } }); };IE用戶數(shù)據(jù)
用以下代碼:
然后利用setAttribute()方法保存數(shù)據(jù)
再調(diào)用save()方法保存到指定的數(shù)據(jù)空間
下一次頁面載入后就可以使用load()方法讀取數(shù)據(jù)
Web儲存機(jī)制最初的Web Storage規(guī)范包含了兩種對象的定義:sessionStorage和globalStorage,這兩種都是在windows對象屬性中存在的。
Storage類型該類型提供最大的存儲空間來存儲名值對,有一下方法:
clear()刪除所有值;
key(index)獲得index處的名字;
getItem(name)根據(jù)指定的name獲取對應(yīng)的值;
removeItem(name)刪除name處的名值對;
setItem(name, value)為指定的name設(shè)置一個對應(yīng)的值;
其中后三中可以直接調(diào)用也可以通過Storage對象間接調(diào)用。
還可以使用length屬性來判斷有多少名值對兒存放在Storage對象中,但無法判斷對象中所有數(shù)據(jù)的大小,不過IE8提供了一個remainingSpace屬性,用于獲取還可以使用的存儲空間的字節(jié)數(shù)。
sessionStorage對象sessionStorage對象存儲特定于某個會話的數(shù)據(jù),也就是該數(shù)據(jù)只保持到該瀏覽器關(guān)閉。存儲在sessionStorage中的數(shù)據(jù)可以跨越頁面刷新而存在,同時如果瀏覽器支持,瀏覽器崩潰并重啟之后依然可用(Firefox和WebKit都支持,IE則不行)。存儲在sessionStorage中的數(shù)據(jù)只能由最初給定對象存儲數(shù)據(jù)的頁面訪問到,所以對頁面應(yīng)用有限制。
存儲數(shù)據(jù)可以使用setItem()或者直接設(shè)置新的屬性來存儲數(shù)據(jù)。下面是這兩種方法的例子。
sessionStorage.setItem("name", "Oliver"); //使用方法存儲數(shù)據(jù) sessionStorage.book = "JSON.com"; //使用屬性存儲數(shù)據(jù)
Firefox和Webkit實現(xiàn)了同步寫入,所以添加到存儲空間中的數(shù)據(jù)是立刻被提交的。而IE的實現(xiàn)則是異步寫入數(shù)據(jù),所以在設(shè)置數(shù)據(jù)和將數(shù)據(jù)實際寫入磁盤之間可能有一些延遲。
在IE8中可以強制把數(shù)據(jù)寫入磁盤:在設(shè)置新數(shù)據(jù)之前使用
begin()方法
并且所有設(shè)置完成之后調(diào)用
commit()方法
看以下例子:
sessionStorage.begin(); sessionStorage.name = "oli"; sessionStorage.commit();讀取數(shù)據(jù)
getItem()
可以使用getItem()或者通過直接訪問屬性名來獲取數(shù)據(jù)。
sessionStorage.name = "oli"; sessionStorage.age = 18; var val = sessionStorage.name; var val_1 = sessionStorage.age; console.log(val); //oli console.log(val_1); //18迭代數(shù)據(jù)
key()方法
通過結(jié)合length屬性和key()方法來迭代sessionStorage中的值
for (var i = 0, len = sessionStorage.length; i < len; i++) { var key = sessionStorage.key(i); var val = sessionStorage.getItem(key); console.log(key + "=" + val); };
for-in方法
還可以使用for-in循環(huán)來迭代sessionStorage中的值:
for (key in sessionStorage) { var value = sessionStorage.getItem(key); console.log(key + "=" + value); }刪除數(shù)據(jù)
removeItem()方法
要從sessionStorage中刪除數(shù)據(jù),可以使用delete操作符刪除對象屬性,也可調(diào)用removeItem()方法。
sessionStorage.name = "oli"; sessionStorage.age = 18; sessionStorage.removeItem("name"); delete sessionStorage.age;
sessionStorage對象應(yīng)該主要用于僅針對會話的小段數(shù)據(jù)的存儲。
globalStorage對象(被localStorage對象取代)Firefox 2中實現(xiàn)了globalStorage對象。作為最初的Web Storage規(guī)范的一部分,這個對象的目的是跨越會話存儲數(shù)據(jù),但有特定的訪問限制。要使用globalStorage,首先要指定哪些域可以訪問該數(shù)據(jù)??梢酝ㄟ^方括號標(biāo)記使用屬性來實現(xiàn),如以下例子所示。
globalStorage["test.com"].name = "Oliver"; var name = globalStorage["test.com"].name;
其中,globalStorage不是Storage的實例,globalStorage["test.com"]才是
某些瀏覽器允許更加寬泛的訪問限制,比如只根據(jù)頂級域名進(jìn)行限制或者允許全局訪問,如下面例子所示:
//存儲數(shù)據(jù),任何人都可以訪問——不要這樣做! globalStorage[""].name = "Nicholas"; //存儲數(shù)據(jù),可以讓任何以.net結(jié)尾域名訪問——不要這樣做! globalStorage["net"].name = "Nicholas";
要避免使用這種可寬泛訪問的數(shù)據(jù)存儲
對globalStorage空間的訪問,是一句發(fā)起請求的頁面的域名、協(xié)議和端口來限制的。例如,如果使用HTTPS協(xié)議在w3cmm.com中存儲了數(shù)據(jù),那么通過HTTP訪問的w3cmm.com的頁面就不能訪問該數(shù)據(jù)。
globalStorage的每個屬性都是Storage的實例。因此,可以像如下代碼中這樣使用。
globalStorage["www.test.com"].name = "Nicholas"; globalStorage["www.test.com"].book = "Professional JavaScript"; globalStorage["www.test.com"].removeItem("name"); var book = globalStorage["www.test.com"].getItem("book");
如果你事先不能確定域名,那么使用location.host作為屬性名比較安全。例如:
globalStorage[location.host].name = "Nicholas"; var book = globalStorage[location.host].getItem("book");localStorage對象
localStorage對象在修訂過的HTML5規(guī)范中作為持久保存在客戶端數(shù)據(jù)的方案取代了globalStorage。要訪問同一個localStorage對象,頁面必須來自同一個域名(子域名無效),使用同一種協(xié)議,在同一個端口上。這相當(dāng)于globalStorage[location.host]。
由于localStorage是Storage的實例,所以可以像使用sessionStorage一樣來使用它。下面是一些例子。
localStorage.setItem("name", "Oliver"); localStorage.book = "JSON"; var book = localStorage.book; var name = localStorage.getItem("name"); localStorage.removeItem("name"); delete localStorage.book; localStorage.clear();storage事件
對Storage對象進(jìn)行任何修改,都會在文檔上觸發(fā)storage事件。當(dāng)通過屬性或setItem()方法保存數(shù)據(jù),使用delete操作符或removeItem()刪除數(shù)據(jù),或著調(diào)用clear()方法時,都會發(fā)生該事件。這個事件的event對象有以下屬性。
domain:發(fā)生變化的存儲空間的域名。
key:設(shè)置或著刪除的鍵名。
newValue:如果是設(shè)置值,則是新值;如果是刪除鍵,則是null。
oldValue:鍵被更改之前的值。
如下代碼:
var EventUtil = { addHandler: function(element, type, handler) { if (element.addEventListener) { element.addEventListener(type, handler, false); } else if (element.attachEvent) { element.attachEvent("on" + type, handler); } else { element["on" + type] = handler; } } }; EventUtil.addHandler(document, "storage", function(event) { alert("Storage changed for " + event.domain); });限制
與其它客戶端數(shù)據(jù)存儲方案類似,Web Storage同樣也有限制。這些限制因瀏覽器而異。一般來說,對存儲空間大小的限制都是以每個來源(協(xié)議、域和端口)為單位的。
對于localStorage而言,大多數(shù)桌面瀏覽器會設(shè)置每個來源5MB的限制。Chrome和Safari對每個來源的限制是2.5MB。而ios版Safari和Android版Webkit的限制也是2.5MB。
對sessionStorage的限制也是因瀏覽器而異。有的瀏覽器對sessionStorage的大小沒有限制,但Chrome、Safari、ios版Safari和Android版Webkit都有限制,也都是2.5MB。IE8+和Opera對sessionStorage的限制是5MB。
IndexedDB推薦一篇文章使用 IndexedDB,來自MDN,鏈接地址:https://developer.mozilla.org/zh-CN/docs/Web/API/IndexedDB_API/Using_IndexedDB
Indexed Database API 簡稱為IndexedDB,是在瀏覽器中保存結(jié)構(gòu)化數(shù)據(jù)的一種數(shù)據(jù)庫。
設(shè)計思想是建立一套API,方便保存和讀取JavaScript對象,同時還支持查詢和搜索。
該操作完全是異步進(jìn)行的。
差不多每一次IndexedDB操作,都需要注冊onerror或onsuccess事件處理程序,以確保適當(dāng)?shù)靥幚斫Y(jié)果。
在使用時需要加上瀏覽器提供商前綴:
var indexDB = window.indexedDB || window.msIndexedDB || window.mozIndexedDB || window.webkitIndexedDB;打開數(shù)據(jù)庫
indexDB.open()
IndexedDB就是一個數(shù)據(jù)庫,IndexedDB最大的特色是使用對象保存數(shù)據(jù),而不是使用表來保存數(shù)據(jù)。
使用IndexedDB前首先要打開它,即把要打開的數(shù)據(jù)庫名傳給indexDB.open()。如果傳入的數(shù)據(jù)庫已經(jīng)存在,就會發(fā)送一個打開它的請求;如果傳入的數(shù)據(jù)庫還不存在,就會發(fā)送一個創(chuàng)建并打開它的請求;
總之,調(diào)用indexedDB.open()會返回一個IDBRequest對象,在這個對象上可以添加onerror和onsuccess事件處理程序。
var request, database; request = indexedDB.open("Base"); request.onerror = function () { console.log(event.target.errorCode); }; request.onsuccess = function () { database = event.target.result; console.log(event.target.result); //IDBDatabase {} 指向數(shù)據(jù)庫實例對象 console.log(event.target); //IDBOpenDBRequest {} 指向request對象 };
ABORT_ERR錯誤碼8 : A request was aborted,
example, through a call to IDBTransaction.abort.
CONSTRAINT_ERR錯誤碼4 : A mutation operation in the transaction failed because a constraint was not satisfied.For example, an object, such as an object store or index, already exists and a request attempted to create a new one.
DATA_ERR錯誤碼5 : Data provided to an operation does not meet requirements.
NON_TRANSIENT_ERR錯誤碼2 : An operation was not allowed on an object.Unless the cause of the error is corrected, retrying the same operation would result in failure.
NOT_ALLOWED_ERR錯誤碼6 :
An operation was called on an object where it is not allowed or at a time when it is not allowed.It also occurs
if a request is made on a source object that has been deleted or removed.
More specific variants of this error includes: TRANSACTION_INACTIVE_ERR and READ_ONLY_ERR.
NOT_FOUND_ERR錯誤碼3 : The operation failed because the requested database object could not be found;
example, an object store did not exist but was being opened.
QUOTA_ERR錯誤碼11 : Either there "s not enough remaining storage space or the storage quota was reached and the user declined to give more space to the database.
READ_ONLY_ERR錯誤碼9 : A mutation operation was attempted in a READ_ONLY transaction.
TIMEOUT_ERR錯誤碼10 : A lock
the transaction could not be obtained in a reasonable time.
TRANSACTION_INACTIVE_ERR錯誤碼7 : A request was made against a transaction that is either not currently active or is already finished.
UNKNOWN_ERR錯誤碼1 : The operation failed
reasons unrelated to the database itself, and it is not covered by any other error code--
for example, a failure due to disk IO errors.
VER_ERR錯誤碼12 : A request to open a database with a version lower than the one it already has.This can only happen with IDBOpenDBRequest.
數(shù)據(jù)庫版本號indexedDB.setVersion()設(shè)置版本號
indexedDB.version獲取版本號
默認(rèn)情況下,IndexedDB數(shù)據(jù)庫是沒有版本號的。最好一開始就調(diào)用setVersion()方法為數(shù)據(jù)庫指定一個版本號(傳入一個表示版本號的字符串)。
目前就chrome瀏覽器,版本號方法已不再適用,另外,創(chuàng)建database后chrome瀏覽器自動設(shè)置版本號為"1":
var request, database; request = indexedDB.open("Base"); request.onerror = function () { console.log(event.target.errorCode); }; request.onsuccess = function () { database = event.target.result; console.log(database.setVersion); //undefined console.log(database.version); //1 };
要更新數(shù)據(jù)庫的 schema,也就是創(chuàng)建或者刪除對象存儲空間,需要實現(xiàn) onupgradeneeded 處理程序,這個處理程序?qū)鳛橐粋€允許你處理對象存儲空間的 versionchange 事務(wù)的一部分被調(diào)用。
request.onupgradeneeded
如:
// 該事件僅在較新的瀏覽器中被實現(xiàn) request.onupgradeneeded = function(event) { // 更新對象存儲空間和索引 .... };
如需設(shè)置數(shù)據(jù)庫版本號,用下面方法:(舊)
var request, database; request = indexedDB.open("Base"); request.onerror = function() { console.log(event.target.errorCode); }; request.onsuccess = function() { database = event.target.result; if (database.version != "1.0") { request = database.setVersion("1.0"); request.onerror = function() { console.log(event.target.errorCode); }; request.onsuccess = function() { console.log("database name: " + database.name + "; version: " + database.version); }; } else { console.log("database name: " + database.name + "; version: " + database.version); //database name: Base; version: 1 }; };創(chuàng)建對象存儲空間
建立完數(shù)據(jù)庫連接以后,就要創(chuàng)建對象存儲空間。
鍵的提供可以有幾種不同的方法,這取決于對象存儲空間是使用 key path 還是 key generator。
若要保存用戶記錄由用戶名、密碼組成,那么保存一條記錄的對象應(yīng)該如下所示:
var userData = [{ username: "007", firstName: "James", lastName: "Bond", password: "foo" }, { username: "005", firstName: "Oliver", lastName: "Young", password: "boo" }];
其中username為鍵(keyPath),這個應(yīng)該是全局唯一的(代表一個user)。
下面是為了保存用戶記錄而創(chuàng)建對象存儲空間的示例:
var request = indexedDB.open("Base", 2); //注意填寫版本號 request.onerror = function() { console.log(event.target.errorCode); }; request.onupgradeneeded = function() { var database = event.target.result; var store = database.createObjectStore("users", { keyPath: "username" }); //根據(jù)username創(chuàng)建一個名為users的對象集合(表) };
獲得了對象存儲空間的引用之后,就可以使用
向?qū)ο蟠鎯臻g添加數(shù)據(jù)add()或put()方法向其中添加數(shù)據(jù)
這兩個方法都接收一個參數(shù),即要保存的對象,然后這個對象就會被保存到存儲空間中。
這兩個方法的區(qū)別在于,如果空間中已經(jīng)包含了鍵值相同的對象:add()會返回錯誤;put()則會重寫原有對象;
可以使用下面的代碼初始化(add()方法)存儲空間:
request.onupgradeneeded = function() { var database = event.target.result; var store = database.createObjectStore("users", { keyPath: "username" }); for (var i in userData) { store.add(userData[i]); } };
for-in循環(huán)可用下面代碼代替:
//users中保存著一批的用戶對象 var i = 0, request, requests[], len = users.length; while (i < len) { request = store.add(users[i++]); request.onerror = function() { // 錯誤處理 }; request.onsuccess = function() { // 成功 }; requests.push(request); }
以下為完整的創(chuàng)建數(shù)據(jù)庫和存儲空間以及初始化數(shù)據(jù)的代碼例子:
// //數(shù)據(jù)在這里userData // var userData = [{ username: "007", //username唯一 firstName: "James", lastName: "Bond", password: "foo" }, { username: "005", firstName: "Oliver", lastName: "Young", password: "boo" }]; // //創(chuàng)建數(shù)據(jù)庫Alldata // var request = indexedDB.open("allData"); request.onerror = function() { console.log(event.target.errorCode); }; request.onsuccess = function() { var database = event.target.result; console.log("數(shù)據(jù)庫已經(jīng)創(chuàng)建:" + database.name + "; 版本號:" + database.version); }; // //創(chuàng)建存儲空間(表)users,并初始化數(shù)據(jù) // var request = indexedDB.open("allData", 2); request.onupgradeneeded = function() { var database = event.target.result; //創(chuàng)建存儲空間 var store = database.createObjectStore("users", { keyPath: "username" }); //添加數(shù)據(jù) for (var i in userData) { store.add(userData[i]); } };
另外,下面是數(shù)據(jù)庫結(jié)構(gòu):
indexedDB |-allData數(shù)據(jù)庫 |-users存儲空間(表) |-(userData數(shù)據(jù))事務(wù)(讀取、修改數(shù)據(jù))
在數(shù)據(jù)庫對象上調(diào)用transaction()方法就可以創(chuàng)建事務(wù)。任何時候,想要讀取或修改數(shù)據(jù),都要通過事務(wù)來組織所有的操作。
下面的代碼保證只加載users存儲空間中的數(shù)據(jù),以便通過事務(wù)進(jìn)行訪問:
var transaction = database.transaction("users");
要訪問多個對象存儲空間,可以傳入字符串?dāng)?shù)組:
var transaction = db.transaction(["users", "anotherStore"]);
上面的兩個事務(wù)都是以只讀的方式訪問數(shù)據(jù)。要修改訪問方式,必須在創(chuàng)建事務(wù)時傳入第二個參數(shù)。
訪問模式默認(rèn)都是以只讀的方式訪問數(shù)據(jù),要修改訪問方式,必須傳入第二個參數(shù),這個參數(shù)表示訪問模式:
READ_ONLY(0)表示只讀;
READ_WRITE(1)表示讀寫;
VERSION_CHANGE(2)表示改變
注意: 舊版實驗性的實現(xiàn)使用不建議使用的常量 IDBTransaction.READ_WRITE 而不是 "readwrite"。
所以現(xiàn)在一般表示讀寫應(yīng)該傳入字符串"readwrite"
其中,上面三個訪問模式已經(jīng)被改為:
"readonly"只讀;
"readwrite"讀寫;
如下:
var request = database.transaction("users", "readonly");訪問存儲空間
objectStore()方法,并傳入存儲空間的名稱,就可以訪問特定的存儲空間了。
就可以:
使用add()和put()方法添加數(shù)據(jù);
使用get()可以取得值;
使用delete()可以刪除對象;
使用clear()可以刪除所有對象;
get()和delete()方法都接收一個對象鍵作為參數(shù)。所有的這5個方法都會返回一個新的請求對象。例如:
var request = database.transaction("users", "readonly").objectStore("users").get("007"); request.onsuccess = function () { var result = event.target.result; //"James" console.log(result.firstName); }; var request = database.transaction("users", "readwrite").objectStore("users").delete("005");
事務(wù)本身也有事件處理程序:onerror和oncomplete。
這兩個事件可以提供事務(wù)級的狀態(tài)信息。
注意:通過oncomplete事件的事件對象訪問不到get()請求返回的任何數(shù)據(jù),必須在onsuccess事件處理程序中才能訪問到。
以下為實例:
var userData = [{ username: "007", //username唯一 firstName: "James", lastName: "Bond", password: "foo" }, { username: "005", firstName: "Oliver", lastName: "Young", password: "boo" }]; //創(chuàng)建數(shù)據(jù)庫Alldata var request = indexedDB.open("allData"); request.onerror = function() { console.log(event.target.errorCode); }; request.onsuccess = function() { var database = event.target.result; console.log("數(shù)據(jù)庫已經(jīng)創(chuàng)建:" + database.name + "; 版本號:" + database.version); }; //創(chuàng)建存儲空間(表)users并初始化數(shù)據(jù) var request = indexedDB.open("allData", 2); var database; request.onupgradeneeded = function() { database = event.target.result; //創(chuàng)建存儲空間 var store = database.createObjectStore("users", { keyPath: "username" }); //添加數(shù)據(jù) for (var i in userData) { store.add(userData[i]); } }; var newPerson = { username: "001", firstName: "Troy", lastName: "Ruby", password: "hello" }; //事務(wù) var request = indexedDB.open("allData", 2); request.onsuccess = function () { var database = event.target.result; // var request = database.transaction("users").objectStore("users").add(newPerson); //報錯,因為只讀,需要設(shè)置為"readwrite" var request = database.transaction("users", "readwrite").objectStore("users").add(newPerson); var request = database.transaction("users", "readonly").objectStore("users").get("007"); request.onsuccess = function () { var result = event.target.result; //"James" console.log(result.firstName); }; var request = database.transaction("users", "readwrite").objectStore("users").delete("005"); };使用游標(biāo)查詢
游標(biāo)就是指向結(jié)果集的一個指針,在對象存儲空間上調(diào)用;在需要檢索多個對象的情況下,需要在事務(wù)內(nèi)部創(chuàng)建游標(biāo)。注意,必須在事務(wù)內(nèi)部創(chuàng)建!
openCursor()方法可以創(chuàng)建游標(biāo)。
openCursor()方法返回的也是一個請求對象,也需要為該對象指定onsuccess和onerror事件處理函數(shù)
var transaction = database.transaction("users", "readonly").objectStore("users").openCursor();
或者:
var store = db.transaction("users").objectStore("users"), request = store.openCursor(); request.onsuccess = function(event) { // 處理成功 }; request.onerror = function(event) { // 處理失敗 };IDBCursor
在前面的onsuccess事件處理程序執(zhí)行時,可以通過event.target.result取得存儲空間中的下一個對象。
IDBCursor實例具有以下幾個屬性:
key: 對象的鍵;
value:實際的對象;
direction:數(shù)值,表示游標(biāo)走動的方向。
默認(rèn)是IDBCursor.NEXT(0), 表示下一項。
IDBCursor.NEXT_TO_DUPLICATE(1), 表示下一個不重復(fù)的項;
IDBCursor.PREV(2)表示前一項;
IDBCursor.PREV_NO_DUPLICATE表示前一個不重復(fù)的項。
primaryKey:游標(biāo)使用的鍵,有可能是對象鍵,也有可能是索引鍵(后面會討論索引)
檢索結(jié)果信息要檢索某個信息的結(jié)果,如下代碼:
var transaction = database.transaction("users", "readonly").objectStore("users").openCursor(); transaction.onsuccess = function() { var cursor = event.target.result; if (cursor) { console.log(cursor); //IDBCursorWithValue {}direction: "next"key: "005"primaryKey: "005"source: IDBObjectStorevalue: Object__proto__: IDBCursorWithValue console.log(cursor.value); //Object {username: "005", firstName: "Oliver", lastName: "Young", password: "boo"} console.log(cursor.key); //005 console.log("Key: " + cursor.key + "; Value: " + JSON.stringify(cursor.value)); //Key: 005; Value: {"username":"005","firstName":"Oliver","lastName":"Young","password":"boo"} } };
注意:返回的cursor.value是一個對象,必要時需要用到JSON.stringify方法
使用游標(biāo)更新記錄update()方法更新記錄
調(diào)用update()方法可以使用指定的對象更新當(dāng)前游標(biāo)的value:
var transaction = database.transaction("users", "readwrite").objectStore("users").openCursor(); transaction.onsuccess = function() { var cursor = event.target.result; if (cursor) { if (cursor.key == "005") { console.log(cursor.value.firstName); //游標(biāo)在第一個位置”005“所以他的firstName就是"Oliver"; 刷新瀏覽器,顯示的結(jié)果則為Oli var value = cursor.value; //更改當(dāng)前游標(biāo)所指的對象("005")的firstName為"Oli"; value.firstName = "Oli"; var updateRequest = cursor.update(value); //使用update方法請求保存更新 updateRequest.onerror = function () { console.log(event.target.errorCode); }; updateRequest.onsuccess = function () { console.log("success"); //success }; } } }; transaction.onerror = function() { console.log(event.target.errorCode); };使用游標(biāo)刪除記錄
delete()方法刪除記錄
如:
var transaction = database.transaction("users", "readwrite").objectStore("users").openCursor(); transaction.onsuccess = function() { var cursor = event.target.result; if (cursor) { if (cursor.key == "005") { var deleteRequest = cursor.delete(); //請求刪除此項 deleteRequest.onerror = function () { // body... }; deleteRequest.onsuccess = function () { // body... }; } } };
注意:如果當(dāng)前的事務(wù)沒有修改對象存儲空間的權(quán)限,update()和delete()會拋出錯誤。
移動游標(biāo)默認(rèn)情況下每個游標(biāo)只發(fā)起一次請求;要想發(fā)起另一次請求,必須調(diào)用下面的一個方法:
continue(key): 移動到結(jié)果集的下一項。參數(shù)key是可選的,不指定這個參數(shù),游標(biāo)移動到下一項;指定這個參數(shù)的話,游標(biāo)會移動到指定鍵的位置。
advance(count): 向前移動count指定的項數(shù)。
遍歷使用移動游標(biāo)的方法,可以用來遍歷存儲空間中的所有項:
var transaction = database.transaction("users", "readwrite").objectStore("users").openCursor(); transaction.onsuccess = function() { var cursor = event.target.result; if (cursor) { console.log("Key: " + cursor.key + "; Value: " + JSON.stringify(cursor.value)); cursor.continue(); //移動下一項 } else { console.log("done"); } };
調(diào)用continue()會觸發(fā)另一次請求,進(jìn)而再次調(diào)用onsuccess處理程序。如果沒有更多項可以遍歷時,event.target.result的值為null。
鍵范圍 IDBKeyRange鍵范圍由IDBKeyRange的實例表示。
有四中定義鍵范圍的方式:
only()方法:var onlyrange = IDBKeyRange.only("007"); var transaction = database.transaction("users", "readwrite").objectStore("users").openCursor(onlyrange);
將onlyrange變量傳入openCursor方法中
lowerBound()方法:第二種定義鍵范圍的方法是指定結(jié)果集的下界。下界表示游標(biāo)開始的位置。
如果想要忽略鍵為"007"的對象本身,從它的下一個對象開始,可以傳入第二個參數(shù)true:
var lowerBound = IDBKeyRange.lowerBound("003", true); //第二個參數(shù)為true表示不包括003 var transaction = database.transaction("users", "readwrite").objectStore("users").openCursor(lowerBound);upperBound()方法
第三種定義鍵范圍的方法是指定結(jié)果集的上界,也就是指定游標(biāo)不能超過哪個鍵。
如果不想包含鍵為指定值的對象,同樣傳入第二個參數(shù)true:
var upperBound = IDBKeyRange.upperBound("005", true); //第二個參數(shù)為true表示不包括005 var transaction = database.transaction("users", "readwrite").objectStore("users").openCursor(upperBound);bound()方法
使用bound()方法可以同時指定上下界。
這個方法可以接收四個參數(shù):表示下界的鍵,表示上界的鍵,可選的表示是否跳過下界的布爾值和可選的表示是否跳過上界的布爾值。
var bound = IDBKeyRange.bound("003", "005", true, false); //第三和第四個參數(shù)為true和false表示不包括003包括005 var transaction = database.transaction("users", "readwrite").objectStore("users").openCursor(bound);設(shè)定游標(biāo)方向
openCursor()可以接收兩個參數(shù),一個是剛才的IDBKeyRange實例,第二個是表示方向的數(shù)值常量,也就是前面講到的IDBCursor中的常量。
正常情況下,游標(biāo)都是從存儲空間的第一項開始,調(diào)用continue()或advance()前進(jìn)到最后一項。游標(biāo)的默認(rèn)方向值是
IDBCursor.NEXT或IDBCursor.NEXT_NO_DUPLICATE
IDBCursor.next或IDBCursor.nextunique
也可以創(chuàng)建一個游標(biāo),從最后一個對象開始,逐個迭代,直到第一個對象,這時要傳入的常量是:
IDBCursor.PREV或IDBCursor.PREV_NO_DUPLICATE
IDBCursor.prev或IDBCursor.prevunique
索引對于有些數(shù)據(jù),需要創(chuàng)建多個鍵,如把用戶ID作為主鍵,以用戶名創(chuàng)建索引
創(chuàng)建索引首先引用對象存儲空間,然后調(diào)用
createIndex()方法
如下:
request.onupgradeneeded = function() { var database = event.target.result; var store = database.createObjectStore("users", { keyPath: "username" }); for (var i in userData) { store.add(userData[i]); } var index = store.createIndex("firstName", "firstName", { unique: false }); //創(chuàng)建名為firstName的索引,屬性名為firstName,屬性值非唯一 };使用索引
index()方法
如下:
var index = database.transaction("users").objectStore("users").index("firstName"); console.log(index); //IDBIndex對象索引上創(chuàng)建游標(biāo)
openCursor()方法
如下:
var request = index.openCursor(); request.onsuccess = function () { console.log(event.target.result); //IDBCursorWithValue對象 };
遍歷:
var request = index.openCursor(); request.onsuccess = function() { var cursor = event.target.result; //IDBCursorWithValue對象 if (cursor) { console.log(cursor.key + "; " + JSON.stringify(cursor.value)); cursor.continue(); } else { console.log("done"); } // Alice; { // "username": "003", // "firstName": "Alice", // "lastName": "Young", // "password": "boo" // } // (index): 87 James; { // "username": "007", // "firstName": "James", // "lastName": "Bond", // "password": "foo" // } // (index): 87 Oliver; { // "username": "005", // "firstName": "Oliver", // "lastName": "Young", // "password": "boo" // } // (index): 90 done };索引上創(chuàng)建主鍵的游標(biāo)
openKeyCursor()方法
調(diào)用這個特殊的只返回每條記錄主鍵的游標(biāo),這個方法在event.result.key中保存索引鍵,在event.result.value中保存的則是主鍵,而不是整個對象
索引中取得對象get()方法
只要傳入相應(yīng)的索引鍵即可:
var store = db.transaction("users").objectStore("users"); var index = store.index("firstName"); var request = index.get("007");根據(jù)索引鍵取得主鍵
getKey()方法
這個方法中event.result.value等于主鍵的值,而不是整個對象:
var store = db.transaction("users").objectStore("users"); var index = store.index("firstName"); var request = index.getKey("007");索引IDBIndex對象的屬性
name:索引的名字
keyPath:createIndex方法中屬性的路徑
objectStore:索引的對象存儲空間
unique:表示索引鍵是否唯一
訪問所有索引indexNames屬性
如:
var indexNames = store.indexNames; for (var i = 0, len = store.indexNames.length; i < len; i++) { var index = store.index(indexNames[i]); console.log(index.name); //firstName //lastName };刪除索引
deleteIndex()
如:
store.deleteIndex("firstName");并發(fā)問題
每次打開數(shù)據(jù)庫,都應(yīng)該指定onversionchange事件處理程序:
request.onsuccess = function() { database = event.target.result; database.onversionchange = function () { database.close(); }; };
當(dāng)設(shè)置version時,指定請求的onblocked事件處理程序也很重要:
var request = database.setVersion("2.0"); request.onblocked = function () { alert("輕先關(guān)閉其他標(biāo)簽頁后再嘗試"); }; request.onsuccess = function () { //處理成功,繼續(xù) };限制
同源
多個限制5MB大小
Firefox不允許本地訪問IndexedDB
完整的例子var userData = [{ username: "007", firstName: "James", lastName: "Bond", password: "foo" }, { username: "005", firstName: "Oliver", lastName: "Young", password: "boo" }, { username: "003", firstName: "Alice", lastName: "Young", password: "boo" }]; var newData = { username: "001", firstName: "Ali", lastName: "Bound", password: "hello" }; var anotherNewData = { username: "001", firstName: "holyshit", lastName: "Bound", password: "hello" }; var dbName = "allData", dbVersion = 1, dbStoreName = "users"; var db; //初始化數(shù)據(jù)庫 function initDb() { console.log("initDb..."); //初始化數(shù)據(jù)庫... var req = indexedDB.open(dbName, dbVersion); req.onsuccess = function() { db = this.result; console.log("initDb Done."); }; req.onerror = function() { console.log("initDb:", event.target.errorCode); }; req.onupgradeneeded = function() { console.log("initDb.onupgradeneeded"); var store = event.target.result.createObjectStore(dbStoreName, { keyPath: "username" }); //這里不能用db,而是event.target.result; store.createIndex("firstName", "firstName", { unique: false }); store.createIndex("lastName", "lastName", { unique: false }); }; } initDb(); //添加數(shù)據(jù) function addData(data) { console.log("add data..."); var req = indexedDB.open(dbName, dbVersion); req.onsuccess = function() { var transaction = db.transaction(dbStoreName, "readwrite"); var store = transaction.objectStore(dbStoreName); if (Object.prototype.toString.call(data).toString() === "[object Array]") { for (var i in data) { store.add(data[i]); } } else if (Object.prototype.toString.call(data).toString() === "[object Object]") { store.add(data); } else { console.log("adding data: please choose Array or Object."); } }; } addData(userData); //提取數(shù)據(jù) function getData(key, callback) { console.log("get data..."); var req = indexedDB.open(dbName, dbVersion); req.onsuccess = function() { var transaction = db.transaction(dbStoreName, "readonly"); var store = transaction.objectStore(dbStoreName); var data = store.get(key); data.onsuccess = function() { var result = event.target.result; if (result) { callback(result); console.log("get data done."); } }; }; } // getData("003", function (result) { // console.log(result); // }); //刪除數(shù)據(jù) function deleteData(key) { console.log("delete data..."); var req = indexedDB.open(dbName, dbVersion); req.onsuccess = function() { var transaction = db.transaction(dbStoreName, "readwrite"); var store = transaction.objectStore(dbStoreName); var data = store.delete(key); data.onsuccess = function() { console.log("delete data done."); }; }; } // deleteData("003"); //清空數(shù)據(jù) function clearData() { console.log("delete data..."); var req = indexedDB.open(dbName, dbVersion); req.onsuccess = function() { var transaction = db.transaction(dbStoreName, "readwrite"); var store = transaction.objectStore(dbStoreName); var data = store.clear(); data.onsuccess = function() { console.log("clear data done."); }; }; } // clearData(); //游標(biāo)提取數(shù)據(jù) function cursorGetData(key, callback) { console.log("cursor get data..."); var req = indexedDB.open(dbName, dbVersion); req.onsuccess = function() { var transaction = db.transaction(dbStoreName, "readonly"); var store = transaction.objectStore(dbStoreName); var cursor = store.openCursor(); cursor.onsuccess = function() { var cursor = event.target.result; if (cursor.key !== key) { cursor.continue(); } else { var result = cursor.value; callback(result); console.log("cursor get data done."); } }; }; } // cursorGetData("007", function (result) { // console.log(result); // }); //游標(biāo)修改數(shù)據(jù) function cursorUpdateData(key, property, newValue) { console.log("cursor update data..."); var req = indexedDB.open(dbName, dbVersion); req.onsuccess = function() { var transaction = db.transaction(dbStoreName, "readwrite"); var store = transaction.objectStore(dbStoreName); var cursor = store.openCursor(); cursor.onsuccess = function() { var cursor = event.target.result; if (cursor.key !== key) { cursor.continue(); } else { var target = cursor.value; for (var i in target) { if (i === property) { var value = Object.defineProperty(target, property, { value: newValue }); var updateReq = cursor.update(value); console.log("cursor update data done."); } } } }; }; } // cursorUpdateData("003", "firstName", "Ali"); //游標(biāo)刪除數(shù)據(jù) function cursorDeleteData(key) { console.log("cursor delete data..."); var req = indexedDB.open(dbName, dbVersion); req.onsuccess = function() { var transaction = db.transaction(dbStoreName, "readwrite"); var store = transaction.objectStore(dbStoreName); var cursor = store.openCursor(); cursor.onsuccess = function() { var cursor = event.target.result; if (cursor.key !== key) { cursor.continue(); } else { var deleteReq = cursor.delete(); console.log("cursor delete data done."); } }; }; } // cursorDeleteData("003"); //游標(biāo)遍歷所有項 function cursorTraversalData(callback) { console.log("cursor tarversal data..."); var req = indexedDB.open(dbName, dbVersion); var result = []; req.onsuccess = function() { var transaction = db.transaction(dbStoreName, "readonly"); var store = transaction.objectStore(dbStoreName); var cursor = store.openCursor(); cursor.onsuccess = function() { var cursor = event.target.result; if (cursor) { result.push(cursor.value); cursor.continue(); } else { console.log("cursor traversal data done."); if (result.length > 0) { callback(result); } } }; }; } // cursorTraversalData(function (result) { // for (var i in result) { // console.log(JSON.stringify(result[i])); // } // }); //遍歷范圍內(nèi)所有項 function boundTraversalData(lower, upper, boo1, boo2, callback) { console.log("bound tarversal data..."); var req = indexedDB.open(dbName, dbVersion); var result = []; req.onsuccess = function() { var transaction = db.transaction(dbStoreName, "readonly"); var store = transaction.objectStore(dbStoreName); var bound = IDBKeyRange.bound(lower, upper, boo1, boo2); var cursor = store.openCursor(bound); cursor.onsuccess = function() { var cursor = event.target.result; if (cursor) { result.push(cursor.value); cursor.continue(); } else { console.log("bound traversal data done."); if (result.length > 0) { callback(result); } } }; }; } // boundTraversalData("003", "007", true, true, function(result) { // for (var i in result) { // console.log(JSON.stringify(result[i])); // } // }); //索引中取得對象 function indexGetData(index, key, callback) { console.log("index get data..."); var req = indexedDB.open(dbName, dbVersion); req.onsuccess = function() { var transaction = db.transaction(dbStoreName, "readonly"); var store = transaction.objectStore(dbStoreName); var target = store.index(index); var data = target.get(key); data.onsuccess = function() { var result = event.target.result; if (result) { callback(result); console.log("index get data done."); } else { console.log("index get data: error output."); } }; }; } // indexGetData("firstName", "Alice", function (result) { // console.log(result); // }); //索引中取得主鍵 function indexGetKey(index, key, callback) { console.log("index get data..."); var req = indexedDB.open(dbName, dbVersion); req.onsuccess = function() { var transaction = db.transaction(dbStoreName, "readonly"); var store = transaction.objectStore(dbStoreName); var target = store.index(index); var data = target.getKey(key); data.onsuccess = function() { var result = event.target.result; if (result) { callback(result); console.log("index get key done."); } else { console.log("index get key: error output."); } }; }; } // indexGetKey("firstName", "Alice", function (result) { // console.log(result); // }); //訪問所有索引 function getAllIndex(callback) { console.log("get all index..."); var req = indexedDB.open(dbName, dbVersion); req.onsuccess = function() { var transaction = db.transaction(dbStoreName, "readonly"); var store = transaction.objectStore(dbStoreName); var indexNames = store.indexNames; if (indexNames.length) { for (var i = 0, len = store.indexNames.length; i < len; i++) { var index = store.index(indexNames[i]); callback(index); } } }; } // getAllIndex(function (index) { // console.log(index.name); // console.log(index.keyPath); // console.log(index.objectStore.name); // console.log(index.unique); // });
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/78915.html
摘要:在線離線應(yīng)用緩存就是一個從瀏覽器的緩存中分出來的緩存去,在緩存中保存數(shù)據(jù),可以使用一個描述文件,列出要下載和緩存的資源。 離線檢測 HTML5中定義的: navigator.onLine如果為true則表示設(shè)備能夠上網(wǎng) 注意是大寫的L(onLine); 用下面代碼檢測屬性狀態(tài): if (navigator.onLine) { // statement if online } e...
摘要:字節(jié)流這個簡單的模型將數(shù)據(jù)存儲為長度不透明的字節(jié)字符串變量,將任何形式的內(nèi)部組織留給應(yīng)用層。字節(jié)流數(shù)據(jù)存儲的代表例子包括文件系統(tǒng)和云存儲服務(wù)。使用同步存儲會阻塞主線程,并為應(yīng)用程序的創(chuàng)建凍結(jié)體驗。 這是專門探索 JavaScript 及其所構(gòu)建的組件的系列文章的第 16 篇。 想閱讀更多優(yōu)質(zhì)文章請猛戳GitHub博客,一年百來篇優(yōu)質(zhì)文章等著你! 如果你錯過了前面的章節(jié),可以在這里找到它...
摘要:應(yīng)用緩存的應(yīng)用緩存,或者簡稱為,是專門為開發(fā)離線應(yīng)用而設(shè)計的。應(yīng)用緩存還有很多相關(guān)的事件,表示其狀態(tài)的改變。數(shù)據(jù)存儲,通常直接叫做,最初是在客戶端用于存儲會話信息的。也就是使用值來存儲多個名稱值對兒。 所謂Web離線應(yīng)用,就是在設(shè)備不能上網(wǎng)的情況下仍然可以運行的應(yīng)用。開發(fā)離線Web應(yīng)用需要幾個步驟:(1)確保應(yīng)用知道設(shè)備是否能上網(wǎng);(2)應(yīng)用還必須能訪問一定的資源(圖像、JavaScr...
摘要:離線檢測含義設(shè)備能否上網(wǎng)代碼注和,和最新的沒問題應(yīng)用緩存緩存的目的是專門為網(wǎng)頁離線設(shè)計的,當(dāng)然在在線情況也會緩存機(jī)制當(dāng)用戶在地址輸入請求的地址去請求網(wǎng)頁時,瀏覽器會先本地緩存中查看是否有對應(yīng)的緩存文件,如果有然后查看新鮮度就是是否過期了,如 23.1 離線檢測 含義:設(shè)備能否上網(wǎng) 代碼: navigator.onLine 注:IE6+和safari+5,firefox3+和ope...
摘要:離線應(yīng)用與客戶端存儲離線檢測定義了屬性來檢測設(shè)備是在線還是離線。應(yīng)用緩存還有很多相關(guān)的事件,表示其狀態(tài)的改變。 離線應(yīng)用與客戶端存儲 離線檢測 HTML5定義了navigator.onLine屬性來檢測設(shè)備是在線還是離線。這個屬性為true表示設(shè)備能上網(wǎng),值為false表示設(shè)備離線。這個屬性的關(guān)鍵是瀏覽器必須知道設(shè)備能否訪問網(wǎng)絡(luò),從而返回正確的值 不同瀏覽器之間有小差異 IE6+...
閱讀 786·2021-08-23 09:46
閱讀 928·2019-08-30 15:44
閱讀 2586·2019-08-30 13:53
閱讀 3039·2019-08-29 12:48
閱讀 3847·2019-08-26 13:46
閱讀 1780·2019-08-26 13:36
閱讀 3510·2019-08-26 11:46
閱讀 1408·2019-08-26 10:48