【杭州網(wǎng)站設(shè)計(jì)】HTML5本地存儲(Local Storage) 的前世今生(二)
分享 2011.07.28 瀏覽次數(shù):6886次
HTML5本地存儲(Local Storage) 的前世今生(二)
原文連接:http://diveintohtml5.org/storage.html (深入HTML5)
作者:Mark Pilgrim
譯者 : feijia (tiimfei@gmail.com)
這篇文章是作者的書HTML5 up & Running的的一個(gè)章節(jié),并在線以 CC-BY-3.0 License授權(quán)。
這是本文的第二部分,第一部分鏈接:
深入HTML5: HTML5 本地存儲( Local Storage )的前世今生 (一)
追蹤HTML5 存儲區(qū)域中的數(shù)據(jù)變化
除了常用的存取數(shù)據(jù)的方法,開發(fā)者還需要能夠偵測數(shù)據(jù)變化的編程接口。這就是存儲事件(storage event )
當(dāng) setItem(),removeItem()或者clear() 方法被調(diào)用,并且數(shù)據(jù)真的發(fā)生了改變時(shí),storage事件就會被觸發(fā)。注意這里的的條件是數(shù)據(jù)真的發(fā)生了變化。也就是說,如果當(dāng)前的存儲區(qū)域是空的,你再去調(diào)用clear()是不會觸發(fā)事件的。或者你通過setItem()來設(shè)置一個(gè)與現(xiàn)有值相同的值,事件也是不會觸發(fā)的。
所有支持localStorage對象的瀏覽器都支持存儲事件,也包括IE8。 不過由于IE8不支持W3C標(biāo)準(zhǔn)的addEventListener (IE9 支持)。因此要在不同瀏覽器中偵聽存儲事件,仍然需要一些代碼來兼顧瀏覽器之間事件處理機(jī)制的不同。
當(dāng)然你也可以使用jQuery,Dojo 或者其他Javacript類庫來幫你注冊事件處理函數(shù),存儲事件也是可以支持的。
- if (window.addEventListener) {
- window.addEventListener('storage', handle_storage, false);
- } else {
- window.attachEvent('onstorage', handle_storage);
- };
上面代碼中handle_storage 是在存儲事件發(fā)生時(shí)被調(diào)用的回調(diào)函數(shù),傳入?yún)?shù)是StorageEvent。 在IE中,該event對象會被保存在window.event 中。
- function handle_storage(e) {
- if (!e) { e = window.event; }
- }
StorageEvent對象會包含下列的屬性。
屬性 | 類型 | 描述 |
---|---|---|
key |
string | 被修改的鍵。 |
oldValue |
any | 修改前的值(如果是增加新的鍵值,則該屬性為null) |
newValue |
any | 修改后的值(如果是刪除鍵值,則該屬性為null) |
url * |
string | 觸發(fā)當(dāng)前存儲事件的頁面的url |
* 注意: url 屬性早期的規(guī)范中為uri屬性。 有些瀏覽器發(fā)布較早,沒有包含這一變更。為兼容性考慮,使用url屬性前,你應(yīng)該先檢查它是否存在,如果沒有url屬性,則應(yīng)該使用uri屬性 |
要注意一點(diǎn),在存儲事件的處理函數(shù)中是不能取消這個(gè)存儲動作的。存儲事件只是瀏覽器在數(shù)據(jù)變化發(fā)生之后給你的一個(gè)通知。
目前技術(shù)的局限
前面的章節(jié)中, 我提到了過去許多用來實(shí)現(xiàn)瀏覽器本地存儲的技術(shù)和插件的缺點(diǎn),例如存儲容量的限制。其實(shí)HTML5本地存儲標(biāo)準(zhǔn)也有它自身的局限。簡單來說就是這幾個(gè)關(guān)鍵詞,“5M容量'和 “QUOTA_EXCEEDED_ERR“ 。
“5M 容量',是每個(gè)來源(origin)(http://www.whatwg.org/specs/web-apps/current-work /multipage/origin-0.html#origin-0)允許存儲容量的默認(rèn)限制。在HTML5 存儲標(biāo)準(zhǔn)中,5M只不過是作為一個(gè)建議的數(shù)值出現(xiàn)的,但是這個(gè)建議被所有的瀏覽器所采用。挺奇怪的,不是嗎? 需要注意的是,存儲的數(shù)據(jù)都是以字符串形式保存的。因此如果你存儲了大量整型數(shù)或浮點(diǎn)數(shù),這些數(shù)也會以字符串形式保存。浮點(diǎn)數(shù)的每一位都需要一個(gè)字符來表示。 這大大增加了所需要的存儲空間。
第二個(gè)關(guān)鍵詞“QUOTA_EXCEEDED_ERR” 是一個(gè)異常,如果你使用的存儲容量超過了5M,你就會碰到它。
接下來你自然會要問那如果我想使用超過5M的容量,是不是可以通過彈出對話框讓用戶授權(quán)的方式來增加允許容量么?很遺憾,答案是”不行!“ 在這篇文章寫作時(shí),(2月 2011), 沒有瀏覽器支持允許程序向用戶請求更大存儲空間的機(jī)制。 有些瀏覽器(例如Opera)允許用戶自己來控制每個(gè)站點(diǎn)可使用的存儲容量,但是這必須由用戶自己主動發(fā)起才行,作為開發(fā)者你沒有辦法來發(fā)起這樣的請求。
HTML5 本地存儲 實(shí)戰(zhàn)
這一節(jié)讓我們來實(shí)際操作一下HTML5 本地存儲。 回憶一下我們在canvas章節(jié)中開發(fā)的Halma 游戲。由于沒有加入本地存儲支持,每次關(guān)閉瀏覽器這個(gè)游戲的進(jìn)度就會丟失。現(xiàn)在我們可以用HTML5 本地存儲技術(shù)在瀏覽器中保存玩家的游戲進(jìn)度。這里是一個(gè)演示。
試試看,在游戲中操作一些步驟,然后關(guān)閉該標(biāo)簽頁然后在新標(biāo)簽頁中再打開該游戲頁面。如果你的瀏覽器支持HTML5本地存儲,你會發(fā)現(xiàn)關(guān)閉前的游戲進(jìn)度和狀態(tài)被神奇的記錄下來了。
這是怎么實(shí)現(xiàn)的呢? 在游戲中,每次發(fā)生狀態(tài)變化,我們都會調(diào)用下面的方法:
- function saveGameState() {
- if (!supportsLocalStorage()) { return false; }
- localStorage['halma.game.in.progress'] = gGameInProgress;
- for (var i = 0; i < kNumPieces; i++) {
- localStorage['halma.piece.' + i + '.row'] = gPieces[i].row;
- localStorage['halma.piece.' + i + '.column'] = gPieces[i].column;
- }
- localStorage['halma.selectedpiece'] = gSelectedPieceIndex;
- localStorage['halma.selectedpiecehasmoved'] = gSelectedPieceHasMoved;
- localStorage['halma.movecount'] = gMoveCount;
- return true;
首先保存一個(gè)標(biāo)志變量”gGameInProgress'用來指示當(dāng)前是否有一個(gè)游戲正在進(jìn)行。 然后是保存正在進(jìn)行中的游戲的狀態(tài),包括哪些棋子被選中了,當(dāng)前一共走的總步數(shù)等等 。
在每次頁面加載時(shí),我們會調(diào)用resumeGame()方法,這個(gè)方法會先檢查本地存儲中的halma.game.in.progress'標(biāo)志,如果是true,則會恢復(fù)上次保存的游戲狀態(tài)。如果false,則調(diào)用newGame開始新游戲。
- function resumeGame() {
- if (!supportsLocalStorage()) { return false; }
- gGameInProgress = (localStorage['halma.game.in.progress'] == 'true');
- if (!gGameInProgress) { return false; }
- gPieces = new Array(kNumPieces);
- for (var i = 0; i < kNumPieces; i++) {
- var row = parseInt(localStorage['halma.piece.' + i + '.row']);
- var column = parseInt(localStorage['halma.piece.' + i + '.column']);
- gPieces[i] = new Cell(row, column);
- }
- gNumPieces = kNumPieces;
- gSelectedPieceIndex = parseInt(localStorage['halma.selectedpiece']);
- gSelectedPieceHasMoved = localStorage['halma.selectedpiecehasmoved'] == 'true';
- gMoveCount = parseInt(localStorage['halma.movecount']);
- drawBoard();
- return true;
- }
在上面resumeGame中最重要的一點(diǎn)就是“ 所有HTML5 本地存儲中的數(shù)據(jù)都是以字符串形式保存的,如果你保存了其他數(shù)據(jù)類型,在訪問這些數(shù)據(jù)時(shí)一定要自己對這些數(shù)據(jù)做強(qiáng)制類型轉(zhuǎn)換'。 例如我們保存的標(biāo)志變量gGameInProgress是一個(gè)Boolean類型。 在saveGameState()中我們不需要做任何特別操作
- localStorage['halma.game.in.progress'] = gGameInProgress;
但是在resumeGame中,我們要訪問這個(gè)數(shù)據(jù)時(shí),則必須做從string到Boolean的強(qiáng)制轉(zhuǎn)換
- gGameInProgress = (localStorage['halma.game.in.progress'] == 'true');
類似的,處理數(shù)值類型,例如gMoveCount 變量,在saveGameStat中我們用下面的語句保存一個(gè)整型變量
- localStorage['halma.movecount'] = gMoveCount;
但在resumeGame方法中,則要使用JavaScript的parseInt函數(shù)來將這個(gè)值從字符串轉(zhuǎn)換為整型
- MoveCount = parseInt(localStorage['halma.movecount']);
比鍵值對更強(qiáng)大的未來
相比HTML5標(biāo)準(zhǔn)成型前的混亂狀態(tài),今天HTML5本地存儲的情形前所未有的令人振奮。 新的API被標(biāo)準(zhǔn)化,并且被所有的主流瀏覽器平臺和設(shè)備所支持。 作為看慣了各種不兼容的Web程序員,很少有機(jī)會看到如此美妙一致的現(xiàn)實(shí)。 不過5M的存儲容量以及僅僅能存儲鍵值對這種簡單數(shù)據(jù)結(jié)構(gòu)對于較復(fù)雜的應(yīng)用來說仍然是遠(yuǎn)遠(yuǎn)不夠的。所以客戶端持久化的未來仍然有許多發(fā)展的空間。而現(xiàn)在我們已經(jīng)能看到許多互相競爭的技術(shù)在浮現(xiàn)。
其中一種技術(shù)的大名你也許早就聽到過 'SQL'. (譯者: 這句笑話很冷?。?2007年,Google發(fā)布Gears項(xiàng)目。Gears是一個(gè)跨瀏覽器的插件,其中就包含了一個(gè)基于SQLite的嵌入式數(shù)據(jù)庫。 這一早期原型后來影響了Web SQL DataBase 規(guī)范的建立.
WebSQLDataBase (之前也稱作 WebDB) 在SQL DB之上提供了一層簡單封裝,從而允許你在JavaScript中使用下面的代碼:
(這可不是偽代碼,下面的代碼在4個(gè)瀏覽器里是真的可以工作的?。?/em>
- openDatabase('documents', '1.0', 'Local document storage', 5*1024*1024, function (db) {
- db.changeVersion('', '1.0', function (t) {
- t.executeSql('CREATE TABLE docids (id, name)');
- }, error);
- });
這段代碼的核心就是傳入 executeSql方法的SQL 語句。這里它能夠支持所有的SQL語句,包括SELECTUPDATE, INSERT 和 DELETE。 一切都和后臺的數(shù)據(jù)庫編程沒什么區(qū)別,唯一不同的是你是在JavaScript里調(diào)用的! 太歡樂了!
Web SQL Database 標(biāo)準(zhǔn)已經(jīng)在4個(gè)瀏覽器(以及對應(yīng)的平臺)中被實(shí)現(xiàn)了。
Web SQL Database supportIE Firefox Safari Chrome Opera iPhone Android
· · 4.0+ 4.0+ 10.5+ 3.0+ 2.0+
當(dāng)然,如果你對SQL略微有所了解的話,你就會明白其實(shí)“SQL” 這個(gè)詞更多只是一個(gè)常用術(shù)語而不是一個(gè)真正統(tǒng)一的標(biāo)準(zhǔn)。( 這其實(shí)和HTML5 這個(gè)詞是一樣的 ) 當(dāng)然,我們讀書時(shí)都學(xué)過一個(gè)SQL-92 標(biāo)準(zhǔn),遺憾的是在現(xiàn)實(shí)世界里,沒有一款產(chǎn)品能真正的嚴(yán)格符合這套標(biāo)準(zhǔn)。因此我們知道有甲骨文的SQL,微軟的SQL,MySQL的SQL, PostgreSQL的SQL, SQLite的SQL。 每個(gè)廠商都在自己的數(shù)據(jù)庫產(chǎn)品中加入了特有的SQL新特性。甚至在一個(gè)廠商的產(chǎn)品中,不同的版本間SQL的用法也會產(chǎn)生變化。
這些SQL業(yè)界的紛爭就導(dǎo)致了我們看到在Web SQL Database 規(guī)范中出現(xiàn)了如下的免責(zé)聲明:
本規(guī)范現(xiàn)在碰到了一個(gè)難題: 所有的感興趣的廠商目前都使用了同樣的SQL后臺(Sqllite), 但是我們還需要有更多獨(dú)立的實(shí)現(xiàn)來使本規(guī)范成為一個(gè)標(biāo)準(zhǔn)。目前本規(guī)范中所使用的SQL語法(SQL dialect)只是一個(gè)基于Sqlite所支持的SQL語法的參考,并不會作為將來標(biāo)準(zhǔn)的一部分。
另一個(gè)與此競爭的技術(shù)是 索引數(shù)據(jù)庫(Indexed Database API ), 之前也稱作WebSimpleDB, 不過現(xiàn)在更多人叫它IndexedDB
索引數(shù)據(jù)庫API主要的概念是對象存儲容器(object store),對象存儲容器很像SQL中的數(shù)據(jù)庫概念。每個(gè)數(shù)據(jù)庫(object store)中都有很多記錄(對象),每個(gè)記錄都有很多字段(fields)。每個(gè)字段都有其預(yù)定義好的數(shù)據(jù)類型。 你可以選擇所有記錄的子集,使用游標(biāo)來遍歷所有記錄, 也提供了事務(wù)的概念來保證數(shù)據(jù)完整性和一致性。
所有這些概念都和傳統(tǒng)SQL數(shù)據(jù)庫編程很相似。最主要的區(qū)別在于,Object Store之上不能使用SQL語句這種結(jié)構(gòu)化的查詢語言。 你用不著構(gòu)建像SELECT * from USERS where ACTIVE = 'Y' 這樣的查詢。 你要做的是通過object store 提供的方法在名為USERS的數(shù)據(jù)庫上打開一個(gè)游標(biāo)指針(cursor)來遍歷所有記錄,然后過濾掉那些不滿足條件的記錄,最后在剩下的記錄上使用數(shù)據(jù)訪問方法獲取你所需要的數(shù)據(jù)。 這篇索引數(shù)據(jù)庫入門是一篇很好的教程,里面 詳細(xì)比較了索引數(shù)據(jù)庫和Web SQL 數(shù)據(jù)庫
在本文寫作時(shí),索引數(shù)據(jù)庫只是在FF4 的beta版中被實(shí)現(xiàn)了。 Mozilla已經(jīng)聲明他們永遠(yuǎn)不會去實(shí)現(xiàn)Web SQL 數(shù)據(jù)庫. Google 則說他們正考慮在Chromium和Google Chrome上支持索引數(shù)據(jù)庫
連微軟也說索引數(shù)據(jù)庫是'很好互聯(lián)網(wǎng)解決方案'
那么你究竟能用索引數(shù)據(jù)庫干點(diǎn)什么呢? 在目前的狀況下,除了一些演示之外幾乎什么也做不了。 但是誰知道1年之后會不會就大不一樣了呢。
標(biāo)簽:
杭州網(wǎng)站設(shè)計(jì)公司 杭州網(wǎng)站建設(shè)公司 杭州網(wǎng)站制作公司 杭州網(wǎng)站設(shè)計(jì) 杭州網(wǎng)站建設(shè) 杭州網(wǎng)站制作 杭州精品網(wǎng)站制作 杭州精典網(wǎng)站制作 杭州精品網(wǎng)站設(shè)計(jì)
-
杭州網(wǎng)站設(shè)計(jì)公司:品牌網(wǎng)站開發(fā)助力企業(yè)成長
日期:2024-12-20瀏覽次數(shù):609次
-
杭州網(wǎng)站建設(shè)公司:商城網(wǎng)站建設(shè)的六大關(guān)鍵步驟
日期:2024-12-18瀏覽次數(shù):643次
-
杭州網(wǎng)站制作:醫(yī)院網(wǎng)站設(shè)計(jì)與域名備案的復(fù)雜性探討
日期:2024-12-18瀏覽次數(shù):641次
-
杭州網(wǎng)站制作公司:打造安全可靠的醫(yī)院網(wǎng)站
日期:2024-12-11瀏覽次數(shù):824次
-
杭州網(wǎng)站設(shè)計(jì)公司:數(shù)據(jù)庫在高端網(wǎng)站制作中的關(guān)鍵作用
日期:2024-12-11瀏覽次數(shù):785次
相關(guān)新聞
整合同類新聞,相關(guān)新聞一手掌握
-
嘉興網(wǎng)站建設(shè):如何選擇服務(wù)器?
日期:2020-10-09瀏覽次數(shù):2337次
-
嘉興網(wǎng)站優(yōu)化:頁面外SEO因素
日期:2020-10-09瀏覽次數(shù):2254次
-
營銷型網(wǎng)站建設(shè),執(zhí)行力很重要
日期:2020-06-28瀏覽次數(shù):2366次
-
對于APP定制,你是否有這些疑惑?
日期:2020-06-11瀏覽次數(shù):2483次
-
論微信小程序的實(shí)際價(jià)值
日期:2020-05-27瀏覽次數(shù):2504次
最新新聞
與互聯(lián)網(wǎng)同行,實(shí)時(shí)掌握網(wǎng)建行業(yè)最新動態(tài)
-
年末網(wǎng)購詐騙升溫:海關(guān)罰沒iPad低價(jià)出售
日期:2010-12-09瀏覽次數(shù):7353次
-
杭州定制app,你是否有這些疑惑?
日期:2021-04-15瀏覽次數(shù):4407次
-
杭州網(wǎng)站優(yōu)化需要的耐心和技巧
日期:2021-08-19瀏覽次數(shù):3796次
-
為什么cms建設(shè)網(wǎng)站最好要定制?
日期:2022-04-22瀏覽次數(shù):2886次
-
杭州網(wǎng)站營銷如何促進(jìn)用戶轉(zhuǎn)化?
日期:2023-03-16瀏覽次數(shù):3014次
隨機(jī)新聞
新聞新動態(tài),您需要的新聞管家
洞悉市場趨勢演變讓傳播回歸社會
免費(fèi)獲取網(wǎng)站建設(shè)與網(wǎng)絡(luò)推廣方案報(bào)價(jià)
-
關(guān)于我們
杭州帷拓科技有限公司,是一家新型的全案網(wǎng)絡(luò)開發(fā)公司,作為以互聯(lián)網(wǎng)高端網(wǎng)站建設(shè)、APP開發(fā)、小程序開發(fā)為核心的專業(yè)網(wǎng)絡(luò)技術(shù)服務(wù)供應(yīng)商,帷拓科技致力于全面分析市場環(huán)境、衡量與預(yù)測市場需求、整合區(qū)別于行業(yè)競爭對手的絕對優(yōu)勢,結(jié)合品牌理念深度挖掘項(xiàng)目優(yōu)勢和產(chǎn)品價(jià)值,提升客戶品牌認(rèn)知、認(rèn)可度。
-
我們的客戶
帷拓科技?xì)v經(jīng)十年沉淀,與國內(nèi)外上千家客戶達(dá)成合作關(guān)系,其中穩(wěn)定合作的公司有:浙江華為、浙江移動、浙江5G產(chǎn)業(yè)聯(lián)盟、浙江省社科院、綠城足球俱樂部、娃哈哈雙語學(xué)校、健康中國杭州峰會、科雷機(jī)電等,帷拓科技始終堅(jiān)持“帷有專業(yè),才能拓展無限”的服務(wù)理念,堅(jiān)持“認(rèn)真堅(jiān)持細(xì)節(jié)”的優(yōu)質(zhì)服務(wù)理念,不斷完善自身,成就企業(yè),最終實(shí)現(xiàn)共贏。
-
我們的業(yè)務(wù)
帷拓科技主營業(yè)務(wù)范圍包含互聯(lián)網(wǎng)高端網(wǎng)站建設(shè)、APP開發(fā)、小程序開發(fā)、商城網(wǎng)站建設(shè)、公眾號運(yùn)營以及數(shù)字營銷等,涵蓋了服務(wù)、房產(chǎn)、數(shù)碼、服裝、物流貿(mào)易等行業(yè),根據(jù)品牌現(xiàn)狀,為每個(gè)客戶量身定制項(xiàng)目整體服務(wù)方案,以敏銳的市場洞察力、創(chuàng)新的市場策劃能力,全面把握市場變化,為客戶實(shí)現(xiàn)從企業(yè)到消費(fèi)者的價(jià)值轉(zhuǎn)換。