最近折騰HTML5遊戲須要離線存儲功能,便把目前可用的幾種HTML5存儲方式研究了下,基於HT for Web寫了個綜合的實例,分別利用了Cookie、WebStorage、IndexedDB以及FileSystem四種本地離線存儲方式,對燃氣監控系統的表計位置、朝向、開關以及表值等信息作了CURD的存取操做。html
HTML5的存儲還有一種Web SQL Database方式,雖然還有瀏覽器支持,是惟一的關係數據庫結構的存儲,但W3C以及中止對其的維護和發展,因此這裏咱們也再也不對其進行介紹:Beware. This specification is no longer in active maintenance and the Web Applications Working Group does not intend to maintain it further.node
整個示例主要就是將HT for Web的DataModel數據模型信息進行序列化和反序列化,這個過程很簡單經過dataModel.serialize()將模型序列化成JSON字符串,經過dataModel.deserialize(jsonString)將JSON字符串內存反序列化出模型信息,而存儲主要就是主要就是針對JSON字符串進行操做。程序員
先介紹最簡單的存儲方式LocalStorage,代碼以下,幾乎不用介紹就是Key-Value的簡單鍵值對存儲結構,Web Storage除了localStorage的持久性存儲外,還有針對本次回話的sessionStorage方式,通常狀況下localStorage較爲經常使用,更多可參考 http://www.w3.org/TR/webstorage/web
function save(dataModel){ var value = dataModel.serialize(); window.localStorage['DataModel'] = value; window.localStorage['DataCount'] = dataModel.size(); console.log(dataModel.size() + ' datas are saved'); return value; } function restore(dataModel){ var value = window.localStorage['DataModel']; if(value){ dataModel.deserialize(value); console.log(window.localStorage['DataCount'] + ' datas are restored'); return value; } return ''; } function clear(){ if(window.localStorage['DataModel']){ console.log(window.localStorage['DataCount'] + ' datas are cleared'); delete window.localStorage['DataModel']; delete window.localStorage['DataCount']; } }
最古老的存儲方式爲Cookie,本例中我只能保存一個圖元的信息,這種存儲方式存儲內容頗有限,只適合作簡單信息存儲,存取接口設計得極其反人類,爲了介紹HTML5存儲方案的完整性我順便把他給列上:chrome
function getCookieValue(name) { if (document.cookie.length > 0) { var start = document.cookie.indexOf(name + "="); if (start !== -1) { start = start + name.length + 1; var end = document.cookie.indexOf(";", start); if (end === -1){ end = document.cookie.length; } return unescape(document.cookie.substring(start, end)); } } return ''; } function save(dataModel) { var value = dataModel.serialize(); document.cookie = 'DataModel=' + escape(value); document.cookie = 'DataCount=' + dataModel.size(); console.log(dataModel.size() + ' datas are saved'); return value; } function restore(dataModel){ var value = getCookieValue('DataModel'); if(value){ dataModel.deserialize(value); console.log(getCookieValue('DataCount') + ' datas are restored'); return value; } return ''; } function clear() { if(getCookieValue('DataModel')){ console.log(getCookieValue('DataCount') + ' datas are cleared'); document.cookie = "DataModel=; expires=Thu, 01 Jan 1970 00:00:00 UTC"; document.cookie = "DataCount=; expires=Thu, 01 Jan 1970 00:00:00 UTC"; } }
現在比較實用強大的存儲方式爲Indexed Database API,IndexedDB能夠存儲結構對象,可構建key和index的索引方式查找,目前各瀏覽器的已經逐漸支持IndexedDB的存儲方式,其使用代碼以下,需注意IndexedDB的不少操做接口相似NodeJS的異步回調方式,特別是查詢時連cursor的continue都是異步再次回調onsuccess函數的操做方式,所以和NodeJS同樣使用上不如同步的代碼容易。數據庫
request = indexedDB.open("DataModel"); request.onupgradeneeded = function() { db = request.result; var store = db.createObjectStore("meters", {keyPath: "id"}); store.createIndex("by_tag", "tag", {unique: true}); store.createIndex("by_name", "name"); }; request.onsuccess = function() { db = request.result; }; function save(dataModel){ var tx = db.transaction("meters", "readwrite"); var store = tx.objectStore("meters"); dataModel.each(function(data){ store.put({ id: data.getId(), tag: data.getTag(), name: data.getName(), meterValue: data.a('meter.value'), meterAngle: data.a('meter.angle'), p3: data.p3(), r3: data.r3(), s3: data.s3() }); }); tx.oncomplete = function() { console.log(dataModel.size() + ' datas are saved'); }; return dataModel.serialize(); } function restore(dataModel){ var tx = db.transaction("meters", "readonly"); var store = tx.objectStore("meters"); var req = store.openCursor(); var nodes = []; req.onsuccess = function() { var res = req.result; if(res){ var value = res.value; var node = createNode(); node.setId(value.id); node.setTag(value.tag); node.setName(value.name); node.a({ 'meter.value': value.meterValue, 'meter.angle': value.meterAngle }); node.p3(value.p3); node.r3(value.r3); node.s3(value.s3); nodes.push(node); res.continue(); }else{ if(nodes.length){ dataModel.clear(); nodes.forEach(function(node){ dataModel.add(node); }); console.log(dataModel.size() + ' datas are restored'); } } }; return ''; } function clear(){ var tx = db.transaction("meters", "readwrite"); var store = tx.objectStore("meters"); var req = store.openCursor(); var count = 0; req.onsuccess = function(event) { var res = event.target.result; if(res){ store.delete(res.value.id); res.continue(); count++; }else{ console.log(count + ' datas are cleared'); } }; }
最後是FileSystem API至關於操做本地文件的存儲方式,目前支持瀏覽器很少,其接口標準也在發展制定變化中,例如在我寫這個代碼時大部分文獻使用的webkitStorageInfo已被navigator.webkitPersistentStorage和navigator.webkitTemporaryStorage替代,存儲的文件可經過filesystem:http://www.hightopo.com/persistent/meters.txt’的URL方式在chrome瀏覽器中查找到,甚至可經過filesystem:http://www.hightopo.com/persistent/相似目錄的訪問,所以也能夠動態生成圖片到本地文件,而後經過filesystem:http:***的URL方式直接賦值給img的html元素的src訪問,所以本地存儲打開了一扇新的門,相信之後會冒出更多稀奇古怪的奇葩應用。json
navigator.webkitPersistentStorage.queryUsageAndQuota(function (usage, quota) { console.log('PERSISTENT: ' + usage + '/' + quota + ' - ' + usage / quota + '%'); } ); navigator.webkitPersistentStorage.requestQuota(2 * 1024 * 1024, function (grantedBytes) { window.webkitRequestFileSystem(window.PERSISTENT, grantedBytes, function (fs) { window.fs = fs; }); } ); function save(dataModel) { var value = dataModel.serialize(); fs.root.getFile('meters.txt', {create: true}, function (fileEntry) { console.log(fileEntry.toURL()); fileEntry.createWriter(function (fileWriter) { fileWriter.onwriteend = function () { console.log(dataModel.size() + ' datas are saved'); }; var blob = new Blob([value], {type: 'text/plain'}); fileWriter.write(blob); }); }); return value; } function restore(dataModel) { fs.root.getFile('meters.txt', {}, function (fileEntry) { fileEntry.file(function (file) { var reader = new FileReader(); reader.onloadend = function (e) { dataModel.clear(); dataModel.deserialize(reader.result); console.log(dataModel.size() + ' datas are restored'); }; reader.readAsText(file); }); }); return ''; } function clear() { fs.root.getFile('meters.txt', {create: false}, function(fileEntry) { fileEntry.remove(function() { console.log(fileEntry.toURL() + ' is removed'); }); }); }
Browser-Side的存儲方式還在快速的發展中,其實除了以上幾種外還有Application Cache,相信未來還會有新秀出現,雖然「雲」是大趨勢,但客戶端並不是要走極端的「瘦」方案,這麼多年冒出了這麼多客戶端存儲方式,說明讓客戶端更強大的市場需求是強烈的,固然目前動盪階段苦逼的是客戶端程序員,除了要適配Mouse和Touch,還要適配各類屏,現在還得考慮適配各類存儲,但願本文能在你們選型客戶端存儲方案時有點幫助,最後上段基於HT for Web操做HTML5存儲示例的視頻效果:http://v.youku.com/v_show/id_XODUzODU2MTY0.html
瀏覽器