摘要:對象應該主要用于僅針對會話的小段數據的存儲。如下代碼限制與其它客戶端數據存儲方案類似,同樣也有限制。最好一開始就調用方法為數據庫指定一個版本號傳入一個表示版本號的字符串。目前就瀏覽器,版本號方法已不再適用,另外,創建
Cookie 限制
由于瀏覽器存在各種限制,最好將整個cookie長度限制在4095B以內。
構成cookie由瀏覽器保存的以下幾塊信息構成:
名稱: cookie的名稱必須是經過URL編碼后的字符串。 雖然它是不區分大小寫的, 但是實際應用時建議把它當作區分大小寫來使用。
值: cookie中字符串值, 也必須是經過URI編碼的字符串。
域: 表示cookie對于哪個域有效。
路徑: cookie是針對域中的哪個目錄生效。
失效時間: 表示cookie失效時間的時間戳, 它是GMT格式的日期。 將該事件設置小于當前時, 就相當于刪除了cookie。
安全標識: 指定該標識后, 只有使用SSL請求連接的時候cookie才會發送到服務器。 secure標識是cookie中唯一一個非鍵值對的部分, 它只包含一個secure單詞。
使用分號加空格分開各個信息構成:
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
或使用安全標志:
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-value
JavaScript中的Cookie
在JavaScript中可以通過
document.cookie可以讀取當前域名下的cookie, 是用分號隔開的鍵值對構成的字符串。 類似于name = aa;
age = 15;
注意所有的鍵值對名稱和值都是經過encodeURIComponent() 編碼的, 使用時要進行解碼。
當給document.cookie賦值時, 不會直接覆蓋現有的cookie, 而是會追加一個新的cookie。 例如:
document.cookie = "a=1"; //執行后會看到新增了一個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
以下函數是常用的cookie讀寫刪除方法:
var CookieUtil = {
//根據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;
},
//設置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,保持相同的鍵、域、路徑、安全選項,然后設置失效時間即可
unset: function(name, path, domain, secure) {
this.set(name, "", new Date(0), path, domain, secure);
}
};
可以像下面這樣使用上述方法:
設置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
設置cookie路徑、域等:
CookieUtil.set("name","Oliver","/","localhost",null,false);
否則使用下面的代碼創建和刪除cookie:
//新cookie
document.cookie = encodeURIComponent("name") + "=" + encodeURIComponent("Oliver");
//刪除上面創建的cookie
document.cookie = encodeURIComponent("name") + "=" + encodeURIComponent("Oliver") + "; expires=" + new Date(0);
舉例
css:
DOM:
welcome to my site!
關閉
js:
子Cookie
由于瀏覽器cookie數量是有限制的,為了減少cookie數量可以使用子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值分隔成數組 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; } }設置整個cookie
setAll設置整個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)) { //屬性名和屬性值編碼后=連接為字符串,并放到數組中 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(); } //設置整個cookie document.cookie = cookieText; }設置單個子cookie
set設置單個子cookie
set: function(name, subName, value, expires, path, domain, secure) { //獲取當前cookie對象 var subcookies = this.getAll(name) || {}; //單個cookie對應的屬性替換 subcookies[subName] = value; //重新設置cookie this.setAll(name, subcookies, expires, path, domain, secure); }刪除cookie
刪除整個cookie, 將失效時間設置為過期日期即可。
unsetAll: function(name, path, domain, secure) { this.setAll(name, null, new Date(0), path, domain, secure); }刪除單個子cookie
刪除單個子cookie,需要先獲取所有子cookie對象,然后刪除子cookie對應的屬性,最后再將子cookie對象重新設置回去。
unset: function(name, subName, path, domain, secure) { //獲取當前cookie對象 var subcookies = this.getAll(name); if (subcookies) { //刪除子cookie對應的屬性 delete subcookies[subName]; //重新設置cookie this.setAll(name, subcookies, null, path, domain, secure); } }以下函數是常用的子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值分隔成數組 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)) { //屬性名和屬性值編碼后=連接為字符串,并放到數組中 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(); } //設置整個cookie document.cookie = cookieText; }, set: function(name, subName, value, expires, path, domain, secure) { //獲取當前cookie對象 var subcookies = this.getAll(name) || {}; //單個cookie對應的屬性替換 subcookies[subName] = value; //重新設置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) { //獲取當前cookie對象 var subcookies = this.getAll(name); if (subcookies) { //刪除子cookie對應的屬性 delete subcookies[subName]; //重新設置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
設置cookie:
//若cookie為document.cookie=data=name=Oliver&book=jsbook; document.cookie = "data" + "=" + "name" + "=" + "Oliver" + "&" + "book" + "=" + "jsbook"; //設置兩個cookie SubCookieUtil.set("data", "name", "Nicholas"); SubCookieUtil.set("data", "book", "HTMLreference") console.log(document.cookie); //data=name=Nicholas&book=HTMLreference //設置全部子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"); //點擊關閉按鈕新建cookie并關閉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當存在則關閉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用戶數據
用以下代碼:
然后利用setAttribute()方法保存數據
再調用save()方法保存到指定的數據空間
下一次頁面載入后就可以使用load()方法讀取數據
Web儲存機制最初的Web Storage規范包含了兩種對象的定義:sessionStorage和globalStorage,這兩種都是在windows對象屬性中存在的。
Storage類型該類型提供最大的存儲空間來存儲名值對,有一下方法:
clear()刪除所有值;
key(index)獲得index處的名字;
getItem(name)根據指定的name獲取對應的值;
removeItem(name)刪除name處的名值對;
setItem(name, value)為指定的name設置一個對應的值;
其中后三中可以直接調用也可以通過Storage對象間接調用。
還可以使用length屬性來判斷有多少名值對兒存放在Storage對象中,但無法判斷對象中所有數據的大小,不過IE8提供了一個remainingSpace屬性,用于獲取還可以使用的存儲空間的字節數。
sessionStorage對象sessionStorage對象存儲特定于某個會話的數據,也就是該數據只保持到該瀏覽器關閉。存儲在sessionStorage中的數據可以跨越頁面刷新而存在,同時如果瀏覽器支持,瀏覽器崩潰并重啟之后依然可用(Firefox和WebKit都支持,IE則不行)。存儲在sessionStorage中的數據只能由最初給定對象存儲數據的頁面訪問到,所以對頁面應用有限制。
存儲數據可以使用setItem()或者直接設置新的屬性來存儲數據。下面是這兩種方法的例子。
sessionStorage.setItem("name", "Oliver"); //使用方法存儲數據 sessionStorage.book = "JSON.com"; //使用屬性存儲數據
Firefox和Webkit實現了同步寫入,所以添加到存儲空間中的數據是立刻被提交的。而IE的實現則是異步寫入數據,所以在設置數據和將數據實際寫入磁盤之間可能有一些延遲。
在IE8中可以強制把數據寫入磁盤:在設置新數據之前使用
begin()方法
并且所有設置完成之后調用
commit()方法
看以下例子:
sessionStorage.begin(); sessionStorage.name = "oli"; sessionStorage.commit();讀取數據
getItem()
可以使用getItem()或者通過直接訪問屬性名來獲取數據。
sessionStorage.name = "oli"; sessionStorage.age = 18; var val = sessionStorage.name; var val_1 = sessionStorage.age; console.log(val); //oli console.log(val_1); //18迭代數據
key()方法
通過結合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循環來迭代sessionStorage中的值:
for (key in sessionStorage) { var value = sessionStorage.getItem(key); console.log(key + "=" + value); }刪除數據
removeItem()方法
要從sessionStorage中刪除數據,可以使用delete操作符刪除對象屬性,也可調用removeItem()方法。
sessionStorage.name = "oli"; sessionStorage.age = 18; sessionStorage.removeItem("name"); delete sessionStorage.age;
sessionStorage對象應該主要用于僅針對會話的小段數據的存儲。
globalStorage對象(被localStorage對象取代)Firefox 2中實現了globalStorage對象。作為最初的Web Storage規范的一部分,這個對象的目的是跨越會話存儲數據,但有特定的訪問限制。要使用globalStorage,首先要指定哪些域可以訪問該數據。可以通過方括號標記使用屬性來實現,如以下例子所示。
globalStorage["test.com"].name = "Oliver"; var name = globalStorage["test.com"].name;
其中,globalStorage不是Storage的實例,globalStorage["test.com"]才是
某些瀏覽器允許更加寬泛的訪問限制,比如只根據頂級域名進行限制或者允許全局訪問,如下面例子所示:
//存儲數據,任何人都可以訪問——不要這樣做! globalStorage[""].name = "Nicholas"; //存儲數據,可以讓任何以.net結尾域名訪問——不要這樣做! globalStorage["net"].name = "Nicholas";
要避免使用這種可寬泛訪問的數據存儲
對globalStorage空間的訪問,是一句發起請求的頁面的域名、協議和端口來限制的。例如,如果使用HTTPS協議在w3cmm.com中存儲了數據,那么通過HTTP訪問的w3cmm.com的頁面就不能訪問該數據。
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規范中作為持久保存在客戶端數據的方案取代了globalStorage。要訪問同一個localStorage對象,頁面必須來自同一個域名(子域名無效),使用同一種協議,在同一個端口上。這相當于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對象進行任何修改,都會在文檔上觸發storage事件。當通過屬性或setItem()方法保存數據,使用delete操作符或removeItem()刪除數據,或著調用clear()方法時,都會發生該事件。這個事件的event對象有以下屬性。
domain:發生變化的存儲空間的域名。
key:設置或著刪除的鍵名。
newValue:如果是設置值,則是新值;如果是刪除鍵,則是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); });限制
與其它客戶端數據存儲方案類似,Web Storage同樣也有限制。這些限制因瀏覽器而異。一般來說,對存儲空間大小的限制都是以每個來源(協議、域和端口)為單位的。
對于localStorage而言,大多數桌面瀏覽器會設置每個來源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,是在瀏覽器中保存結構化數據的一種數據庫。
設計思想是建立一套API,方便保存和讀取JavaScript對象,同時還支持查詢和搜索。
該操作完全是異步進行的。
差不多每一次IndexedDB操作,都需要注冊onerror或onsuccess事件處理程序,以確保適當地處理結果。
在使用時需要加上瀏覽器提供商前綴:
var indexDB = window.indexedDB || window.msIndexedDB || window.mozIndexedDB || window.webkitIndexedDB;打開數據庫
indexDB.open()
IndexedDB就是一個數據庫,IndexedDB最大的特色是使用對象保存數據,而不是使用表來保存數據。
使用IndexedDB前首先要打開它,即把要打開的數據庫名傳給indexDB.open()。如果傳入的數據庫已經存在,就會發送一個打開它的請求;如果傳入的數據庫還不存在,就會發送一個創建并打開它的請求;
總之,調用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 {} 指向數據庫實例對象 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.
數據庫版本號indexedDB.setVersion()設置版本號
indexedDB.version獲取版本號
默認情況下,IndexedDB數據庫是沒有版本號的。最好一開始就調用setVersion()方法為數據庫指定一個版本號(傳入一個表示版本號的字符串)。
目前就chrome瀏覽器,版本號方法已不再適用,另外,創建database后chrome瀏覽器自動設置版本號為"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 };
要更新數據庫的 schema,也就是創建或者刪除對象存儲空間,需要實現 onupgradeneeded 處理程序,這個處理程序將會作為一個允許你處理對象存儲空間的 versionchange 事務的一部分被調用。
request.onupgradeneeded
如:
// 該事件僅在較新的瀏覽器中被實現 request.onupgradeneeded = function(event) { // 更新對象存儲空間和索引 .... };
如需設置數據庫版本號,用下面方法:(舊)
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 }; };創建對象存儲空間
建立完數據庫連接以后,就要創建對象存儲空間。
鍵的提供可以有幾種不同的方法,這取決于對象存儲空間是使用 key path 還是 key generator。
若要保存用戶記錄由用戶名、密碼組成,那么保存一條記錄的對象應該如下所示:
var userData = [{ username: "007", firstName: "James", lastName: "Bond", password: "foo" }, { username: "005", firstName: "Oliver", lastName: "Young", password: "boo" }];
其中username為鍵(keyPath),這個應該是全局唯一的(代表一個user)。
下面是為了保存用戶記錄而創建對象存儲空間的示例:
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" }); //根據username創建一個名為users的對象集合(表) };
獲得了對象存儲空間的引用之后,就可以使用
向對象存儲空間添加數據add()或put()方法向其中添加數據
這兩個方法都接收一個參數,即要保存的對象,然后這個對象就會被保存到存儲空間中。
這兩個方法的區別在于,如果空間中已經包含了鍵值相同的對象: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循環可用下面代碼代替:
//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); }
以下為完整的創建數據庫和存儲空間以及初始化數據的代碼例子:
// //數據在這里userData // var userData = [{ username: "007", //username唯一 firstName: "James", lastName: "Bond", password: "foo" }, { username: "005", firstName: "Oliver", lastName: "Young", password: "boo" }]; // //創建數據庫Alldata // var request = indexedDB.open("allData"); request.onerror = function() { console.log(event.target.errorCode); }; request.onsuccess = function() { var database = event.target.result; console.log("數據庫已經創建:" + database.name + "; 版本號:" + database.version); }; // //創建存儲空間(表)users,并初始化數據 // var request = indexedDB.open("allData", 2); request.onupgradeneeded = function() { var database = event.target.result; //創建存儲空間 var store = database.createObjectStore("users", { keyPath: "username" }); //添加數據 for (var i in userData) { store.add(userData[i]); } };
另外,下面是數據庫結構:
indexedDB |-allData數據庫 |-users存儲空間(表) |-(userData數據)事務(讀取、修改數據)
在數據庫對象上調用transaction()方法就可以創建事務。任何時候,想要讀取或修改數據,都要通過事務來組織所有的操作。
下面的代碼保證只加載users存儲空間中的數據,以便通過事務進行訪問:
var transaction = database.transaction("users");
要訪問多個對象存儲空間,可以傳入字符串數組:
var transaction = db.transaction(["users", "anotherStore"]);
上面的兩個事務都是以只讀的方式訪問數據。要修改訪問方式,必須在創建事務時傳入第二個參數。
訪問模式默認都是以只讀的方式訪問數據,要修改訪問方式,必須傳入第二個參數,這個參數表示訪問模式:
READ_ONLY(0)表示只讀;
READ_WRITE(1)表示讀寫;
VERSION_CHANGE(2)表示改變
注意: 舊版實驗性的實現使用不建議使用的常量 IDBTransaction.READ_WRITE 而不是 "readwrite"。
所以現在一般表示讀寫應該傳入字符串"readwrite"
其中,上面三個訪問模式已經被改為:
"readonly"只讀;
"readwrite"讀寫;
如下:
var request = database.transaction("users", "readonly");訪問存儲空間
objectStore()方法,并傳入存儲空間的名稱,就可以訪問特定的存儲空間了。
就可以:
使用add()和put()方法添加數據;
使用get()可以取得值;
使用delete()可以刪除對象;
使用clear()可以刪除所有對象;
get()和delete()方法都接收一個對象鍵作為參數。所有的這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");
事務本身也有事件處理程序:onerror和oncomplete。
這兩個事件可以提供事務級的狀態信息。
注意:通過oncomplete事件的事件對象訪問不到get()請求返回的任何數據,必須在onsuccess事件處理程序中才能訪問到。
以下為實例:
var userData = [{ username: "007", //username唯一 firstName: "James", lastName: "Bond", password: "foo" }, { username: "005", firstName: "Oliver", lastName: "Young", password: "boo" }]; //創建數據庫Alldata var request = indexedDB.open("allData"); request.onerror = function() { console.log(event.target.errorCode); }; request.onsuccess = function() { var database = event.target.result; console.log("數據庫已經創建:" + database.name + "; 版本號:" + database.version); }; //創建存儲空間(表)users并初始化數據 var request = indexedDB.open("allData", 2); var database; request.onupgradeneeded = function() { database = event.target.result; //創建存儲空間 var store = database.createObjectStore("users", { keyPath: "username" }); //添加數據 for (var i in userData) { store.add(userData[i]); } }; var newPerson = { username: "001", firstName: "Troy", lastName: "Ruby", password: "hello" }; //事務 var request = indexedDB.open("allData", 2); request.onsuccess = function () { var database = event.target.result; // var request = database.transaction("users").objectStore("users").add(newPerson); //報錯,因為只讀,需要設置為"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"); };使用游標查詢
游標就是指向結果集的一個指針,在對象存儲空間上調用;在需要檢索多個對象的情況下,需要在事務內部創建游標。注意,必須在事務內部創建!
openCursor()方法可以創建游標。
openCursor()方法返回的也是一個請求對象,也需要為該對象指定onsuccess和onerror事件處理函數
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事件處理程序執行時,可以通過event.target.result取得存儲空間中的下一個對象。
IDBCursor實例具有以下幾個屬性:
key: 對象的鍵;
value:實際的對象;
direction:數值,表示游標走動的方向。
默認是IDBCursor.NEXT(0), 表示下一項。
IDBCursor.NEXT_TO_DUPLICATE(1), 表示下一個不重復的項;
IDBCursor.PREV(2)表示前一項;
IDBCursor.PREV_NO_DUPLICATE表示前一個不重復的項。
primaryKey:游標使用的鍵,有可能是對象鍵,也有可能是索引鍵(后面會討論索引)
檢索結果信息要檢索某個信息的結果,如下代碼:
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方法
使用游標更新記錄update()方法更新記錄
調用update()方法可以使用指定的對象更新當前游標的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); //游標在第一個位置”005“所以他的firstName就是"Oliver"; 刷新瀏覽器,顯示的結果則為Oli var value = cursor.value; //更改當前游標所指的對象("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); };使用游標刪除記錄
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... }; } } };
注意:如果當前的事務沒有修改對象存儲空間的權限,update()和delete()會拋出錯誤。
移動游標默認情況下每個游標只發起一次請求;要想發起另一次請求,必須調用下面的一個方法:
continue(key): 移動到結果集的下一項。參數key是可選的,不指定這個參數,游標移動到下一項;指定這個參數的話,游標會移動到指定鍵的位置。
advance(count): 向前移動count指定的項數。
遍歷使用移動游標的方法,可以用來遍歷存儲空間中的所有項:
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"); } };
調用continue()會觸發另一次請求,進而再次調用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()方法:第二種定義鍵范圍的方法是指定結果集的下界。下界表示游標開始的位置。
如果想要忽略鍵為"007"的對象本身,從它的下一個對象開始,可以傳入第二個參數true:
var lowerBound = IDBKeyRange.lowerBound("003", true); //第二個參數為true表示不包括003 var transaction = database.transaction("users", "readwrite").objectStore("users").openCursor(lowerBound);upperBound()方法
第三種定義鍵范圍的方法是指定結果集的上界,也就是指定游標不能超過哪個鍵。
如果不想包含鍵為指定值的對象,同樣傳入第二個參數true:
var upperBound = IDBKeyRange.upperBound("005", true); //第二個參數為true表示不包括005 var transaction = database.transaction("users", "readwrite").objectStore("users").openCursor(upperBound);bound()方法
使用bound()方法可以同時指定上下界。
這個方法可以接收四個參數:表示下界的鍵,表示上界的鍵,可選的表示是否跳過下界的布爾值和可選的表示是否跳過上界的布爾值。
var bound = IDBKeyRange.bound("003", "005", true, false); //第三和第四個參數為true和false表示不包括003包括005 var transaction = database.transaction("users", "readwrite").objectStore("users").openCursor(bound);設定游標方向
openCursor()可以接收兩個參數,一個是剛才的IDBKeyRange實例,第二個是表示方向的數值常量,也就是前面講到的IDBCursor中的常量。
正常情況下,游標都是從存儲空間的第一項開始,調用continue()或advance()前進到最后一項。游標的默認方向值是
IDBCursor.NEXT或IDBCursor.NEXT_NO_DUPLICATE
IDBCursor.next或IDBCursor.nextunique
也可以創建一個游標,從最后一個對象開始,逐個迭代,直到第一個對象,這時要傳入的常量是:
IDBCursor.PREV或IDBCursor.PREV_NO_DUPLICATE
IDBCursor.prev或IDBCursor.prevunique
索引對于有些數據,需要創建多個鍵,如把用戶ID作為主鍵,以用戶名創建索引
創建索引首先引用對象存儲空間,然后調用
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 }); //創建名為firstName的索引,屬性名為firstName,屬性值非唯一 };使用索引
index()方法
如下:
var index = database.transaction("users").objectStore("users").index("firstName"); console.log(index); //IDBIndex對象索引上創建游標
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 };索引上創建主鍵的游標
openKeyCursor()方法
調用這個特殊的只返回每條記錄主鍵的游標,這個方法在event.result.key中保存索引鍵,在event.result.value中保存的則是主鍵,而不是整個對象
索引中取得對象get()方法
只要傳入相應的索引鍵即可:
var store = db.transaction("users").objectStore("users"); var index = store.index("firstName"); var request = index.get("007");根據索引鍵取得主鍵
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");并發問題
每次打開數據庫,都應該指定onversionchange事件處理程序:
request.onsuccess = function() { database = event.target.result; database.onversionchange = function () { database.close(); }; };
當設置version時,指定請求的onblocked事件處理程序也很重要:
var request = database.setVersion("2.0"); request.onblocked = function () { alert("輕先關閉其他標簽頁后再嘗試"); }; request.onsuccess = function () { //處理成功,繼續 };限制
同源
多個限制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; //初始化數據庫 function initDb() { console.log("initDb..."); //初始化數據庫... 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(); //添加數據 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); //提取數據 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); // }); //刪除數據 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"); //清空數據 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(); //游標提取數據 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); // }); //游標修改數據 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"); //游標刪除數據 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"); //游標遍歷所有項 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])); // } // }); //遍歷范圍內所有項 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); // });
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/78915.html
摘要:在線離線應用緩存就是一個從瀏覽器的緩存中分出來的緩存去,在緩存中保存數據,可以使用一個描述文件,列出要下載和緩存的資源。 離線檢測 HTML5中定義的: navigator.onLine如果為true則表示設備能夠上網 注意是大寫的L(onLine); 用下面代碼檢測屬性狀態: if (navigator.onLine) { // statement if online } e...
摘要:字節流這個簡單的模型將數據存儲為長度不透明的字節字符串變量,將任何形式的內部組織留給應用層。字節流數據存儲的代表例子包括文件系統和云存儲服務。使用同步存儲會阻塞主線程,并為應用程序的創建凍結體驗。 這是專門探索 JavaScript 及其所構建的組件的系列文章的第 16 篇。 想閱讀更多優質文章請猛戳GitHub博客,一年百來篇優質文章等著你! 如果你錯過了前面的章節,可以在這里找到它...
摘要:應用緩存的應用緩存,或者簡稱為,是專門為開發離線應用而設計的。應用緩存還有很多相關的事件,表示其狀態的改變。數據存儲,通常直接叫做,最初是在客戶端用于存儲會話信息的。也就是使用值來存儲多個名稱值對兒。 所謂Web離線應用,就是在設備不能上網的情況下仍然可以運行的應用。開發離線Web應用需要幾個步驟:(1)確保應用知道設備是否能上網;(2)應用還必須能訪問一定的資源(圖像、JavaScr...
摘要:離線檢測含義設備能否上網代碼注和,和最新的沒問題應用緩存緩存的目的是專門為網頁離線設計的,當然在在線情況也會緩存機制當用戶在地址輸入請求的地址去請求網頁時,瀏覽器會先本地緩存中查看是否有對應的緩存文件,如果有然后查看新鮮度就是是否過期了,如 23.1 離線檢測 含義:設備能否上網 代碼: navigator.onLine 注:IE6+和safari+5,firefox3+和ope...
摘要:離線應用與客戶端存儲離線檢測定義了屬性來檢測設備是在線還是離線。應用緩存還有很多相關的事件,表示其狀態的改變。 離線應用與客戶端存儲 離線檢測 HTML5定義了navigator.onLine屬性來檢測設備是在線還是離線。這個屬性為true表示設備能上網,值為false表示設備離線。這個屬性的關鍵是瀏覽器必須知道設備能否訪問網絡,從而返回正確的值 不同瀏覽器之間有小差異 IE6+...
閱讀 798·2021-08-23 09:46
閱讀 946·2019-08-30 15:44
閱讀 2605·2019-08-30 13:53
閱讀 3052·2019-08-29 12:48
閱讀 3874·2019-08-26 13:46
閱讀 1808·2019-08-26 13:36
閱讀 3522·2019-08-26 11:46
閱讀 1420·2019-08-26 10:48