• 淺談 HTML5 的 DOM Storage 機制

    0
    HTML5 JavaScript PHP Java C/C++ 14062 次瀏覽
    摘要:在 開發 Web 應用時,開發者有時需要在本地存儲數據。當前瀏覽器支持 cookie 存儲,但其大小有 4KB 的限制。這對于一些 Ajax 應用來說是不夠的。更多的存儲空間需要瀏覽器本身或是插件的支持,如 Google Gears 和 Flash。不過開發人員需要通過檢測當前瀏覽器所支持的插件類型來使用對應的接口。 HTML5 中新引入了 DOM Storage 機制,通過使用鍵值對在客戶端保存數據,并且提供了更大容量的存儲空間。本文將詳細論述 HTML5 對本地存儲的支持,并對存儲事件綁定和數據存儲與 JSON 的結合使用進行討論。當一些老版本的瀏覽器不支持 DOM Storage 時,可以考慮用其他的技術如 Dojo 來實現相同的功能。本文也會對其進行簡單的介紹。

      HTML5 是下一代 HTML 標準,開始吸引越來越多人的目光。HTML5 的 DOM Storage 機制提供了一種方式讓程序員能夠把信息存儲到本地的計算機上,在需要時獲取。這點和 cookie 相似,區別是 DOM Storage 提供了更大容量的存儲空間。

      目前,在客戶端保存數據使用最多的是 cookie,但 cookie 的大小上限為 4KB,并且每次請求一個新頁面時 cookie 都會被發送過去。更多的存儲空間需要瀏覽器本身或是插件的支持,例如只在 Internet Explorer 上使用的 userData,需要額外安裝插件的 Google Gears 和 Flash。現在,HTML5 提供了一種標準的接口,使程序員可以簡單地訪問存儲的數據。由于鍵值對存儲在本地計算機上,在頁面加載完畢后可以通過 JavaScript 來操作這些數據。

      DOM Storage

      示例應用程序:用戶注冊

      本文使用的示例應用程序是一個簡單的用戶注冊過程,表單包含三個字段:name、age 和 address,我們將其拆分為兩個表單,分兩個頁面顯示。借助簡化了的數據模型,主要介紹如何利用 DOM Storage 功能處理表單跨頁問題。

      DOM Storage 兩個分類

      DOM Storage 分為 sessionStorage 和 localStorage。

      localStorage 對象和 sessionStorage 對象使用方法基本相同,它們的區別在于作用的范圍不同。sessionStorage 用來存儲與頁面相關的數據,它在頁面關閉后無法使用。而 localStorage 則持久存在,在頁面關閉后也可以使用。

      DOM Storage 接口

      下面是 DOM Storage 的接口定義:

    interface Storage {
    readonly attribute unsigned
    long length;
    getter DOMString key(
    in unsigned long index);
    getter any getItem(
    in DOMString key);
    setter creator
    void setItem(in DOMString key, in any data);
    deleter
    void removeItem(in DOMString key);
    void clear();
    };

      length:返回當前存儲在 Storage 對象中的鍵值對數量。

      key(index):返回列表中第 n 個鍵的名字。Index 從 0 開始。

      getItem(key):返回指定鍵對應的值。

      setItem(key, value):存入一個鍵值對。

      removeItem(key) :刪除指定的鍵值對。

      clear():刪除 Storage 對象中的所有鍵值對。

      通常,使用最多的方法是 getItem 和 setItem。

      以 sessionStorage 為例:

      存儲鍵值對:

      window.sessionStorage.setItem("key1", value1);

      通過鍵名來讀取值:

      var value1 = window.sessionStorage.getItem("key1");

      判斷瀏覽器是否支持 DOM Storage

      要使用 DOM Storage,首先,需要查看當前的瀏覽器是否支持。目前 Internet Explorer 8.0 以上,Firefox 3.5 以上,Chrome 4.0 以上都是支持 DOM Storage 的。

      如果瀏覽器不支持 DOM Storage,可以用其他的方法作為備選,本文還使用 Dojo 提供的 dojox.storage 模塊來實現相同的功能。

      清單 1. 查看瀏覽器是否支持 DOM Storage

     //sessionStorage   if(window.sessionStorage){ 
        alert(“support sessionStorage”); 
     }else{ 
        alert(“not support sessionStorage”); 
        // 不支持 sessionStorage      // 用 dojox.storage 來實現相同功能  } 
    
     //localStorage   if(window.localStorage){ 
        alert(“support localStorage”); 
     }else{ 
        alert(“not support localStorage”); 
        // 不支持 localStorage      // 用 dojox.storage 來實現相同功能  } 

      下面是用戶注冊的兩個表單。清單 2 中的第一個表單有兩個字段 name 和 age 需要用戶填寫內容。填寫完后點擊 Next 按鈕進入下一個頁面,此時函數 saveToStorage 會被調用,把在該頁面輸入的兩個字段的值保存到 sessionStorage 對象中。

      當從下一個頁面退回到本頁面時,使用 windows.onload 在加載頁面的時候將數據從 sessionStorage 中取出,并顯示在輸入框中,方便用戶修改。

      另外,給對象賦值除了用 setItem 方法外,也可以用 window.sessionStorage.key1 = value1。

      清單 2. 第一個表單頁面

     <script type="text/javascript"> 
     // 當退回到第一個頁面時,從 sessionStorage 得到用戶之前輸入的值并顯示在頁面,方便修改  window.onload = function(){ 
        if (window.sessionStorage) { 
            var name = window.sessionStorage.getItem("name"); 
            var age = window.sessionStorage.getItem("age"); 
            if (name != "" || name !=null){ 
                document.getElementById("name").value = name; 
            } 
            if (age !="" || age !=null){ 
                document.getElementById("age").value = age; 
            } 
        } else { 
            // 不支持 sessionStorage,用 Dojo 實現相同功能     } 
     }; // 將數據保存到 sessionStorage 對象中 function saveToStorage() { //sessionStorage  if (window.sessionStorage) { 
            var name = document.getElementById("name").value; 
            var age = document.getElementById("age").value; 
            window.sessionStorage.setItem("name", name); 
            window.sessionStorage.setItem("age", age); 
            window.location.href = "form2.html"; 
        } else { 
            // 不支持 sessionStorage,用 Dojo 實現相同功能     } 
     } 
     </script> 
    
     <form action="./form2.html"> 
        <input type="text" name="name" id="name"> 
        <input type="text" name="age" id="age"> 
        <input type="button" value="Next" onclick="saveToStorage()"></input> 
     </form> 

      清單3 的第二個頁面有一個 address 字段。當用戶填寫完畢后,點擊 Submit 按鈕提交頁面,此時 addStorageValue 函數被調用,把保存在 sessionStorage 中的 name 和 age 值先賦給當前表單的兩個隱藏字段,隨后一起提交給下一個處理表單的頁面。最后調用 removeItem 函數刪除 name 和 age 值。

      如果用戶需要修改第一個頁面填寫的內容,可以點擊 Back 按鈕回到前一個頁面,用戶在前一個頁面已經填寫的內容會出現在 text 框中。

      清單 3. 第二個表單頁面

     <script type="text/javascript"> 
     // 將保持在 sessionStorage 中的數據賦給表單的隱藏屬性 function addStorageValue() { 
        //sessionStorage  if (window.sessionStorage) { 
            var name = window.sessionStorage.getItem("name"); 
            var age = window.sessionStorage.getItem("age"); 
            document.getElementById("name").value = name; 
            document.getElementById("age").value = age; 
            window.sessionStorage.removeItem("name"); 
            window.sessionStorage.removeItem("age"); 
        } else { 
            // 不支持 sessionStorage,用 Dojo 實現相同功能     } 
     } 
    
     function backToPreviousForm() { 
        window.location.href = "form1.html"; 
     } 
     </script> 
    
     <form action="./form3.php" method="post"> 
        <input type="hidden" name="name" id="name"> 
        <input type="hidden" name="age" id="age"> 
        <input type="text" name="address" id="address"> 
        <input type="button" value="Back" onclick="backToPreviousForm()"> 
        <input type="submit" value="Submit" onclick="addStorageValue()"></input> 
     </form> 

      使用 DOM Storage 需要注意的幾點

      保存在 Storage 對象的數據類型

      當使用 DOM Storage 進行本地存儲時,任何數據格式在 Storage 對象中都以字符串類型保存,所以如果保存的數據不是字符串,在讀取的時候需要自己進行類型的轉換。這里我們使用 JSON 將對象序列化之后再存儲。

      JSON (JavaScript Object Notation) 是一種輕量級的數據交換格式。易于人閱讀和編寫,同時也易于機器解析和生成。目前,JSON 已經是 JavaScript 標準的一部分,主流的瀏覽器對 JSON 支持都非常完善。

      本文用到兩個相關的函數

      JSON.parse() 函數會把 JSON 對象轉換為原來的數據類型。

      JSON.stringify() 函數會把要保存的對象轉換成 JSON 對象保存。

      在清單 4 中,先把一個布爾型的數據存到 Storage 對象中,然后再取出,可以看到布爾類型的數據在取出的時候變為字符串。接下來換一種方式保存數據,先用 JSON.stringify 方法序列化數據,然后保存到 Storage 對象中,在取出的時候用 JSON.parse 方法進行反序列化,可以看到讀取出的數據還是布爾類型。

      另外,使用 JSON 保存一個字符串,通過 Chrome 的 Storage 工具,可以看到存入的字符串兩邊有雙引號,這個雙引號表示存入的是一個字符串。當用 JSON 表示一個簡單的字符串時,會在字符串兩邊加上雙引號。最后,該頁面加載后的輸出如下:

      string1 boolean2 string3

      清單 4. 使用 JSON 對 DOM Storage 的復雜數據進行處理

     // 生成一個 Boolean 類型的變量 data1   var data1 = new Boolean(true); 
    
     // 不用 JSON 處理數據  sessionStorage["key1"] = data1; 
     if(sessionStorage["key1"] == "true"){ 
        // 從 Storage 對象讀取出來的數據 data1 變為 String 類型     document.write("string1 "); 
     } 
    
     // 使用 JSON 處理數據 data1   sessionStorage["key2"] = JSON.stringify(data1); 
     if(JSON.parse(sessionStorage["key2"]) == true){ 
        // 從 Storage 對象讀取的數據 data1,用 JSON 將變量轉換為原來的 Boolean 類型     document.write("boolean2 "); 
     } 
    
     // 生成一個 String 類型的變量  var data2 = new String("true"); 
     // 使用 JSON 處理數據,在 Storage 對象中保存的是 “string”  sessionStorage["key3"] = JSON.stringify(data2); 
     data2 = JSON.parse(sessionStorage["key3"]); 
     if(data2 == "true"){ 
        // 變量轉換回來還是 String 類型     document.write("string3"); 
     } 

      使用 Chrome 瀏覽器可以查看當前的 sessionStorage 和 localStorage 的鍵值對。在工具欄選擇工具到開發人員工具到Resources到Local Storage或Session Storage, 可以查看 key 和 value。

      圖 1. Chrome 瀏覽器的 Storage 工具欄
    淺談 HTML5 的 DOM Storage 機制

      綜上所述,我們可以如清單 5 一樣,在加載頁面的時候用 JSON 轉換數據類型,在離開頁面的時候將數據保存為 JSON 對象。這樣,保存在 Storage 中任何類型的數據在讀取的時候都可以轉換為原來的類型。

      清單 5. 使用 JSON 對 DOM Storage 的復雜數據進行處理

     <script type="text/javascript"> 
     var value; 
     function loadValue() { 
        value1 = JSON.parse(window.sessionStorage.getItem(“key1”)); 
     } 
     function saveValue() { 
        window.sessionStorage.setItem(“key1”) = JSON.stringify(value1); 
     } 
    
     window.addEventListener(“load”, loadValue. true); 
     window.addEventListener(“unload”, saveValue. true); 
     </script> 

      空間大小

      HTML5 的建議是每個網站提供給 Storage 的空間是 5MB,一般來說足夠存字符串。如果存入的數據太大,有些瀏覽器如 Chrome 會拋出 QUOTA_EXCEEDED_ERR 異常。所以雖然 DOM Storage 提供的空間比 cookie 要大很多,但在使用需要注意限制。

      圖 2. Chrome 瀏覽器拋出異常
    淺談 HTML5 的 DOM Storage 機制

      安全性

      一般不要在客戶端存儲敏感的信息,使用 localStorage、globalStorage 等在客戶端存儲的信息都非常容易暴露。應該在完成數據存儲后使用 clear 或者 removeItem 方法清除保存在 Storage 對象中的數據。

      存儲事件驅動

      如果想在存儲成功或修改存儲的值時執行一些操作,可以用 DOM Storage 接口提供的事件。可以使用如下方法注冊事件:

      window.addEventListener(storage, handleStorageEvent, false);

      存儲事件接口定義

    interface StorageEvent : Event {
    readonly attribute DOMString key;
    readonly attribute any oldValue;
    readonly attribute any newValue;
    readonly attribute DOMString url;
    readonly attribute Storage storageArea;
    void initStorageEvent(
    in DOMString typeArg, inboolean canBubbleArg, inboolean cancelableArg, in DOMString keyArg, in any oldValueArg, in any newValueArg, in DOMString urlArg, in Storage storageAreaArg);
    };

      key:發生改變的鍵。

      oldValue:鍵改變之前的值。

      newValue:鍵改變之后的值。

      url:觸發存儲事件的頁面 url。

      在清單 6 中注冊完存儲事件后,當 sessionStorage 或者 localStorage 對象的值發生改變時,會觸發 handleStorageEvent 函數,在頁面顯示發生改變的鍵和改變之前與之后的值。

      清單 6. 添加存儲事件

    // 顯示存儲事件的相關內容
    function handleStorageEvent(e) {
        document.write(key
    + e.key + oldValue + e.oldValue + newValue + e.newValue);
    }
    // 添加存儲事件監聽
    window.addEventListener(storage, handleStorageEvent, false);

      使用 Dojo 實現之前用戶注冊的功能

      Dojo 是一個 JavaScript 實現的開源工具包,很大程度上屏蔽了瀏覽器之間的差異性。Dojo 擴展庫 (dojox) 是 Dojo 在其基本庫、核心庫和 Dijit 庫的基礎上提供的一個非常豐富的組件倉庫。本文用到的 dojox.storage 模塊能夠將數據保存在本地存儲中,實現和之前 DOM Storage 一樣的功能。

      由于一些老版本瀏覽器不支持 HTML5,我們還可以用 Dojo 來實現之前用戶注冊的功能。相對于 HTML5 的 DOM Storage 接口,Dojo 的 dojox.storage.Provider 接口提供的方法更多。這里我們列出幾個常用的方法。

      get(key, namespace):返回指定鍵對應的值。

      put(key, value, resultsHandler, namespace):存入一個鍵值對。

      remove(key, namespace):刪除指定的鍵值對。

      clear(namespace):刪除對象中的所有鍵值對。

      現在對第一個表單的 JavaScript 代碼做部分修改,并在頁面中引入 dojox.storage 模塊。這樣,程序在不支持 HTML5 的瀏覽器中能夠通過調用 Dojo 提供的方法正常運行。dojo.require("dojox.storage") 表示引入 dojox.storage 功能模塊。然后通過 dojox.storage.manager.isInitialized() 查看 dojox.storage.manager 是否已經初始化,如果沒有的話,則需要等待其初始化完成之后,再進行存儲操作。

      清單 7. 經過修改后的第一個表單頁面的部分代碼

    <script type="text/javascript">
    dojo.require(
    "dojox.storage");
    // 當退回到第一個頁面時,從 Storage 中得到用戶之前輸入的值并顯示在頁面,方便修改
    // 這里先進行 dojox.storage.manager 的初始化
    if(!dojox.storage.manager.isInitialized()){
    dojo.connect(dojox.storage.manager,
    "loaded", saveAndLoad);
    }
    else{
    dojo.connect(dojo,
    "loaded", saveAndLoad);
    }
    function saveAndLoad(){
    var name;
    var age;
    //sessionStorage
    if (window.sessionStorage) {
    name
    = window.sessionStorage.getItem("name");
    age
    = window.sessionStorage.getItem("age");
    if (name !=""|| name !=null){
    document.getElementById(
    "name").value = name;
    }
    if (age !=""|| age !=null){
    document.getElementById(
    "age").value = age;
    }
    }
    //dojox.storage
    else
    {
    name
    = dojox.storage.get("name");
    age
    = dojox.storage.get("age");
    if (typeof name !="undefined" ){
    document.getElementById(
    "name").value = name;
    }
    if (typeof age !="undefined" ){
    document.getElementById(
    "age").value = age;
    }
    }
    }
    // 保存數據 function saveToStorage() {
    var name = document.getElementById("name").value;
    var age = document.getElementById("age").value;
    //sessionStorage
    if (window.sessionStorage) {
    window.sessionStorage.setItem(
    "name", name);
    window.sessionStorage.setItem(
    "age", age);
    }
    //dojox.storage
    else {
    dojox.storage.put(
    "name", name);
    dojox.storage.put(
    "age", age);
    }
    window.location.href
    ="form2.html";
    }
    </script>

      清單 8. 經過修改后的第二個表單頁面的部分代碼

    <script type="text/javascript">
    dojo.require(
    "dojox.storage");
    // 將保存在 sessionStorage 中的數據賦給表單的隱藏屬性
    function addStorageValue() {
    var name;
    var age;
    //sessionStorage
    if (window.sessionStorage) {
    name
    = window.sessionStorage.getItem("name");
    age
    = window.sessionStorage.getItem("age");
    document.getElementById(
    "name").value = name;
    document.getElementById(
    "age").value = age;
    window.sessionStorage.removeItem(
    "name");
    window.sessionStorage.removeItem(
    "age");
    }
    //dojox.storage
    else {
    name
    = dojox.storage.get("name");
    age
    = dojox.storage.get("age");
    document.getElementById(
    "name").value = name;
    document.getElementById(
    "age").value = age;
    dojox.storage.remove(
    "name");
    dojox.storage.remove(
    "age");
    }
    }
    function backToPreviousForm() {
    window.location.href
    ="form1.html";
    }
    </script>

      結束語

      HTML5 中引入了 DOM Storage 機制用于存儲鍵值對,它的設計目的是提供大規模、易用的存儲功能,并且程序員可以通過調用標準的接口,簡單地訪問存儲的數據。目前,許多新版本的瀏覽器都 支持 DOM Storage 功能。當老版本的瀏覽器不支持 HTML5 提供的 DOM Storage 機制時,可以考慮用 Dojo 來實現相同的功能。

    轉自:http://www.ibm.com/developerworks/cn/web/1107_gaoly_html5storage/

    相似問題

    相關經驗

    相關資訊

    相關文檔

  • sesese色