H5的離線存儲(chǔ)方案

1. Web SQL Database

HTML5的存儲(chǔ)還有一種Web SQL Database方式淮摔,雖然還有瀏覽器支持,是唯一的關(guān)系數(shù)據(jù)庫結(jié)構(gòu)的存儲(chǔ)始赎,但W3C以及停止對其的維護(hù)和發(fā)展和橙,所以這里我們也不再對其進(jìn)行介紹:Beware. This specification is no longer in active maintenance and the Web Applications Working Group does not intend to maintain it further.


Web SQL Database

整個(gè)示例主要就是將HT for Web的DataModel數(shù)據(jù)模型信息進(jìn)行序列化和反序列化,這個(gè)過程很簡單通過dataModel.serialize()將模型序列化成JSON字符串造垛,通過dataModel.deserialize(jsonString)將JSON字符串內(nèi)存反序列化出模型信息魔招,而存儲(chǔ)主要就是主要就是針對JSON字符串進(jìn)行操作。


流程圖

2. LocalStorage

先介紹最簡單的存儲(chǔ)方式LocalStorage五辽,代碼如下办斑,幾乎不用介紹就是Key-Value的簡單鍵值對存儲(chǔ)結(jié)構(gòu),Web Storage除了localStorage的持久性存儲(chǔ)外杆逗,還有針對本次回話的sessionStorage方式乡翅,一般情況下localStorage較為常用。
這兩種存儲(chǔ)方式的API也一樣罪郊,詳細(xì)說明可以自行百度蠕蚜。
獲取某一條:localStorage.getItem("key")、sessionStorage.getItem("key");
存儲(chǔ)某一條:localStorage.setItem("key", value)悔橄、sessionStorage.setItem("key", value);
刪除某一條:localStorage.removeItem("key")波势、sessionStorage.removeItem("key");
刪除所有:localStorage.clear()翎朱、sessionStorage.clear();

localStorage和sessionStorage

3. Cookie

最古老的存儲(chǔ)方式為Cookie,本例中我只能保存一個(gè)圖元的信息尺铣,這種存儲(chǔ)方式存儲(chǔ)內(nèi)容很有限拴曲,只適合做簡單信息存儲(chǔ),存取接口設(shè)計(jì)得極其反人類凛忿,為了介紹HTML5存儲(chǔ)方案的完整性我順便把他給列上:

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"; 
   }
}

4. Indexed Database API

如今比較實(shí)用強(qiáng)大的存儲(chǔ)方式為Indexed Database API澈灼,IndexedDB可以存儲(chǔ)結(jié)構(gòu)對象,可構(gòu)建key和index的索引方式查找店溢,目前各瀏覽器的已經(jīng)逐漸支持IndexedDB的存儲(chǔ)方式叁熔,其使用代碼如下,需注意IndexedDB的很多操作接口類似NodeJS的異步回調(diào)方式床牧,特別是查詢時(shí)連cursor的continue都是異步再次回調(diào)onsuccess函數(shù)的操作方式荣回,因此和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');
     } 
   };
}

5. FileSystem API

最后是FileSystem API相當(dāng)于操作本地文件的存儲(chǔ)方式戈咳,目前支持瀏覽器不多心软,其接口標(biāo)準(zhǔn)也在發(fā)展制定變化中,例如在我寫這個(gè)代碼時(shí)大部分文獻(xiàn)使用的webkitStorageInfo已被navigator.webkitPersistentStorage和navigator.webkitTemporaryStorage替代著蛙,存儲(chǔ)的文件可通過filesystem的URL方式在chrome瀏覽器中查找到删铃,甚至可通過filesy類似目錄的訪問,因此也可以動(dòng)態(tài)生成圖片到本地文件踏堡,然后通過filesystem:http:***的URL方式直接賦值給img的html元素的src訪問猎唁,因此本地存儲(chǔ)打開了一扇新的門,相信以后會(huì)冒出更多稀奇古怪的奇葩應(yīng)用顷蟆。

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');
     });
   }); 
}
FileSystem API

6. 其他

Browser-Side的存儲(chǔ)方式還在快速的發(fā)展中诫隅,其實(shí)除了以上幾種外還有Application Cache,相信將來還會(huì)有新秀出現(xiàn)帐偎,雖然“云”是大趨勢阎肝,但客戶端并非要走極端的“瘦”方案,這么多年冒出了這么多客戶端存儲(chǔ)方式肮街,說明讓客戶端更強(qiáng)大的市場需求是強(qiáng)烈的风题,當(dāng)然目前動(dòng)蕩階段苦逼的是客戶端程序員,除了要適配Mouse和Touch嫉父,還要適配各種屏沛硅,如今還得考慮適配各種存儲(chǔ),希望本文能在大家選型客戶端存儲(chǔ)方案時(shí)有點(diǎn)幫助绕辖。

關(guān)注公眾號【grain先森】摇肌,回復(fù)關(guān)鍵詞 【18福利】,獲取為你準(zhǔn)備的年終福利仪际,更多關(guān)鍵詞玩法期待你的探索~

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末围小,一起剝皮案震驚了整個(gè)濱河市昵骤,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌肯适,老刑警劉巖变秦,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異框舔,居然都是意外死亡蹦玫,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進(jìn)店門刘绣,熙熙樓的掌柜王于貴愁眉苦臉地迎上來樱溉,“玉大人,你說我怎么就攤上這事纬凤「U辏” “怎么了?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵停士,是天一觀的道長挖帘。 經(jīng)常有香客問我,道長向瓷,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任舰涌,我火速辦了婚禮猖任,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘瓷耙。我一直安慰自己朱躺,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布搁痛。 她就那樣靜靜地躺著长搀,像睡著了一般。 火紅的嫁衣襯著肌膚如雪鸡典。 梳的紋絲不亂的頭發(fā)上源请,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天,我揣著相機(jī)與錄音彻况,去河邊找鬼谁尸。 笑死,一個(gè)胖子當(dāng)著我的面吹牛纽甘,可吹牛的內(nèi)容都是我干的良蛮。 我是一名探鬼主播,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼悍赢,長吁一口氣:“原來是場噩夢啊……” “哼决瞳!你這毒婦竟也來了货徙?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤皮胡,失蹤者是張志新(化名)和其女友劉穎痴颊,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體胸囱,經(jīng)...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡祷舀,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了烹笔。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片裳扯。...
    茶點(diǎn)故事閱讀 37,997評論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖谤职,靈堂內(nèi)的尸體忽然破棺而出饰豺,到底是詐尸還是另有隱情,我是刑警寧澤允蜈,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布冤吨,位于F島的核電站,受9級特大地震影響饶套,放射性物質(zhì)發(fā)生泄漏漩蟆。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一妓蛮、第九天 我趴在偏房一處隱蔽的房頂上張望怠李。 院中可真熱鬧,春花似錦蛤克、人聲如沸捺癞。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽髓介。三九已至,卻和暖如春筋现,著一層夾襖步出監(jiān)牢的瞬間唐础,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工矾飞, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留彻犁,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓凰慈,卻偏偏與公主長得像汞幢,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子微谓,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評論 2 345

推薦閱讀更多精彩內(nèi)容