基於HTML5實現的(本地存儲)多標籤頁面元素的複製粘貼

歷史 

在HTML5本地存儲以前,若是咱們想在客戶端保存持久化數據,有這麼幾個選擇: 

html

  1. HTTP cookie。HTTP cookie的缺點很明顯,最多隻能存儲4KB的數據,每一個HTTP請求都會被傳送回服務器,明文傳輸(除非你使用SSL)。
  2. IE userData。userData是微軟在上世紀90年代的瀏覽器大戰時推出的本地存儲方案,藉助DHTML的behaviour屬性來存儲本地數據, 容許每一個頁面最多存儲64K數據,每一個站點最多640K數據,userData的缺點顯而易見,它不是Web標準的一部分,除非你的程序只須要支持IE, 不然它基本沒什麼用處。
  3. Flash cookie。Flash cookie的名字有些誤導,它實際上和HTTP cookie並非一回事,或許它的名字應該叫作"Flash本地存儲」,Flash cookie默認容許每一個站點存儲不超過100K的數據,若是超出了,Flash會自動向用戶請求更大的存儲空間,藉助Flash的 ExternalInterface接口,你能夠很輕鬆地經過Javascript操做Flash的本地存儲。Flash的問題很簡單,就是由於它是 Flash。
  4. Google Gears。Gears是Google在07年發佈的一個開源瀏覽器插件,旨在改進各大瀏覽器的兼容性,Gears內置了一個基於SQLite的嵌入式 SQL數據庫,並提供了統一API對數據庫進行訪問,在取得用戶受權以後,每一個站點能夠在SQL數據庫中存儲不限大小的數據,Gears的問題就是 Google本身都已經不用它了。

現狀 

咱們如今一般所說的HTML5本地存儲,通常指的是Web Storage規範,這個標準曾經是HTML5規範的一部分,但後來由於種種緣由從HTML5規範中分離了出來。可是除了Web Storage,HTML5的本地存儲標準還有另外2個競爭者:Web SQL Database和IndexedDB。下面就讓咱們依次來看看這3個規範吧。 html5

Web Storage 

Web Storage是目前獲得支持最普遍的HTML5本地存儲規範:IE 8+、FF 3.5+、Safari 4+、Chrome 4+、Opera 10.5+,以及iPhone 2+和Android 2+都已經支持Web Storage,要判斷你的瀏覽器是否支持Web Storage,可使用下面這個函數: web

function supports_html5_storage() {  
    try {  
        return 'localStorage' in window && window['localStorage'] !== null;  
    } catch (e) {  
        return false;  
    }  
}  

HTML5 Storage的使用很是簡單: sql

 

var foo = localStorage.getItem("bar");  
// ...  
localStorage.setItem("bar", foo);  

你也能夠寫成下面這樣:數據庫

var foo = localStorage["bar"];  
// ...  
localStorage["bar"] = foo;  

若是要將某個key從存儲空間刪除,能夠調用removeItem:後端

localStorage.removeItem('foo');  

你也能夠像遍歷數組那樣遍歷存儲的全部鍵值對象: api

for(var i=0; ivar key = localStorage.key(i);  
    console.log(key + ":" + localStorage[key]);  
}  

若是你的程序須要在不一樣頁面訪問同一個值,你可能須要瞭解這個值是否已經被其餘頁面改變了,這能夠經過向瀏覽器註冊storage事件來實現:數組

window.addEventListener('storage', function(e) {  
    console.log(e.key + "'s value is changed from '" +  
        e.oldValue + "' to '" + e.newValue + "' by " + e.url);  
}, false);  
  
//A頁面  
localStorage['foo'] = 'bar';  
  
//B頁面  
localStorage['foo'] = 'newBar';  

  這時你應該會在A頁面的Console中看到: 

foo’s value is changed from ‘bar’ to ‘newbar’ by http://localhost/test.html 

要注意的是,storage事件僅僅只是通知你某個鍵對應的值已經發生了改變,你沒有辦法在回調中阻止這個改變發生。 

HTML5 Storage看起來不錯,那它有沒什麼缺點呢?好問題。要說HTML5 Storage的缺點,惟一的問題就是它默認的QUOTA只有5MB,而且你沒辦法經過程序自行或是提示用戶來增長存儲空間。惟一的辦法就是用戶本身打開 瀏覽器的設置,並手動修改QUOTA的大小,若是超出了5MB的限制,你將會遇到一個「QUOTA_EXCEEDED_ERR」的錯誤。 

Web SQL Database 

Web SQL Database是一個已經廢棄的規範,可是鑑於除了IE和Firefox,其餘瀏覽器都已經實現了Web SQL Database,而且它還具備一些HTML5 Storage所不具備的特性,因此仍是值得了解一下的。 

Web SQL Database就像它的名字那樣,就是一個讓你能夠在Web上直接使用的SQL數據庫,你要作的就是打開數據庫,而後執行SQL,和你對Mysql作的事情沒什麼兩樣: 瀏覽器

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

  關於Web SQL Database的更多介紹,能夠參看這篇指南。 

可是它的缺點也一樣明顯。最大的問題就出在SQL上,實際上並不存在一種叫作SQL的標準結構化查詢語言,咱們日常使用的其實是MS SQL、Oracle SQL、MySQL SQL、postgre SQL或者SQLite SQL(儘管有一個叫作SQL-92的規範,但它基本形同虛設),更進一步,甚至都不存在SQLite SQL,咱們使用的其實是SQLite x.y.z SQL,而這也就是Web SQL Database最大的問題,它沒法統一各個瀏覽器廠商實現的SQL語言,若是你的某條Web SQL查詢只能在Chrome上運行,這還能叫作標準嗎? 

因此,若是你如今訪問Web SQL Database的規範頁面,你會在頂部看到這樣一則聲明: 
這個規範已經陷入了一個僵局:目前的全部實現都是基於同一個SQL後端(SQLite),可是咱們須要更多的獨立實現來完成標準化,因此除非有廠商願意獨立實現這個規範,不然當前的SQL規範只能採用SQLite的SQL方言,而做爲一個標準,這是不可接受的。 

IndexedDB 

最後咱們要介紹的就是IndexedDB了,相比其餘兩個規範,目前只有Firefox實現了IndexedDB(順便提一下,Mozilla表示它們永遠不會去實現Web SQL Database),不過Google已經表示正在考慮在Chrome中加入IndexDB支持。 

IndexedDB引入了一個object store的概念,這有點像是一個SQL Database,你能夠在「數據庫」中存儲「記錄」,而且每條「記錄」能夠擁有不少「字段",每一個字段都有一個特定的數據類型,你能夠選擇記錄的子集, 並使用「光標」進行遍歷,同時object store中的全部變動都是基於「事務」的。 

下面讓咱們來看一個小例子: 服務器

var request = window.indexedDB.open("CandyDB",  
                                    "My candy store database");  
request.onsuccess = function(event) {  
  var db = event.result;  
  if (db.version != "1") {  
    // User's first visit, initialize database.  
    var createdObjectStoreCount = 0;  
    var objectStores = [  
      { name: "kids", keyPath: "id", autoIncrement: true },  
      { name: "candy", keyPath: "id", autoIncrement: true },  
      { name: "candySales", keyPath: "", autoIncrement: true }  
    ];  
  
    function objectStoreCreated(event) {  
      if (++createdObjectStoreCount == objectStores.length) {  
        db.setVersion("1").onsuccess = function(event) {  
          loadData(db);  
        };  
      }  
    }  
  
    for (var index = 0; index < objectStores.length; index++) {  
      var params = objectStores[index];  
      request = db.createObjectStore(params.name, params.keyPath,  
                                     params.autoIncrement);  
      request.onsuccess = objectStoreCreated;  
    }  
  }  
  else {  
    // User has been here before, no initialization required.  
    loadData(db);  
  }  
};  

  關於Indexed的更多介紹能夠參看Mozilla Blog的這篇指南。 

-------- 
本文編譯整理自:Mark Pilgrim的Dive Into HTML5 第七章 HTML5本地存儲,靈感來自於 ProcessOn 已經支持多頁面文件元素複製粘貼  編譯:@yuanyiz。

相關文章
相關標籤/搜索