localstorage相容ie8以下瀏覽器的問題
最近在做一個網站,由於希望儘可能減小伺服器的壓力,也想提高網站的運轉速度,就想盡可能少的在伺服器上讀寫資料以及下載重複資料,需要重複使用的資料,就儲存在本地,能在本地進行的運算,盡一切可能在本地完成。
於是就出現一個本地儲存資料的問題。如果ie不是國內最廣泛的瀏覽器,如果ie9(ie8存在一些問題,後面再說)已經得到普及,那麼一切就都很簡單了,用html5的localstorage,一切都變得異常簡單——谷歌瀏覽器早就支援localstorage了,但ie支援得很晚。
問題是,ie8以下的瀏覽器不支援localstorage;據說ie8支援localstorage,但我把ie升級到ie8之後,任然無法使用localstorage——一開始我以為是我的程式有問題,後來又覺得是ie8安裝有問題,重灌之後,我最終確定是ie8的升級程式有問題,微軟的東西總是這麼爛,早已習以為常了——這一來一去,差不多折騰了我三四個小時。
於是乎我確定,即便使用者瀏覽器是ie8,也要考慮無法使用localstorage的可能——而且從前段時間別人使用我的網站的情況來看,這種可能性還很大。
既然ie8要排除在外,而ie9只能在win7上使用,win7現在又遠未達到全面普及的程度——那麼就必須解決低版本ie使用localstorage的相容問題——真是生不逢時,再過幾年就根本不用考慮這個相容問題了。
由於我還屬於剛入門的菜鳥級程式設計師,所以很多東西根本弄不懂,坑爹的是這篇文章給的程式碼零零散散,沒法直接把它的程式碼直接嵌到程式裡,而要弄懂它程式碼的意思又需要大費周章,另外找到幾篇文章,把程式碼放進去,又會冒出一大堆我搞不懂的錯誤。
於是我決定從最基礎的原理開始,自己動手來做相容程式,別人沒有為你定做貼身的程式,就只有靠自己了,好在原理很簡單:
ie瀏覽器在很早的時候就支援一種UserData的本地儲存功能,不過ie的UserData用起來比localstorage麻煩得不止一點半點(當然二者的差異還不止於此),接下來要做的就是用UserData來模擬localstorage的所有功能。
localstorage有幾項核心功能:
1window.localStorage.getItem( key );——讀變數
2window.localStorage.setItem( key, value );——寫變數
3window.localStorage.removeItem( key );——刪除變數
4window.localStorage.clear(); ——變數初始化
5window.localStorage.length;——本地變數的個數;
6window.localStorage.key( i );——按序號讀取變數;
對於我做網站來說,最後兩個功能基本用不上,我就沒寫,但要實現也很簡單,如果你需要的話可以聯絡我,我們一起切磋。
接下來就是要用UserData前面幾項模擬功能,關於UserData的使用方法,我主要是參考了這篇文章:
不過這篇文章也有幾個坑爹的地方,讓我浪費了不少時間。
等我把UserData和localStorage的基本用法都弄懂了之後,我發現上面那篇介紹相容方法的文章有不少亮點,但也有很多不如人意的地方——最大的問題是他是採用了用節點儲存變數的方法,這樣的話變數的總大小不能超過124k,這個規模對我的網站來說太小了,於是我採用了用檔案儲存的方式,這樣變數大小就能達到1M,夠用了。
敲了幾個小時的鍵盤,反覆除錯後,這段程式碼終於可以用了。(程式碼在下面)
使用方法:
(1)把這段程式碼放在第一個進行本地儲存的語句之前的任何位置;
(2)程式碼必須在<html>標籤內;
(3)不能將本地變數名設為"userdata_record"
(4)不能以 userdataobj 命名變數
(5)加入程式碼後,如果不使用localStorage.length和localStorage.key( i ),那麼你就完全按照localStorage的使用方法進行本地儲存就可以了。
如果有問題歡迎和我聯絡。
<script language="JavaScript" type="text/javascript">
if(typeof(localStorage)=='undefined')
{var box = document.body || document.getElementsByTagName("head")[0] || document.documentElement;
userdataobj = document.createElement('input');
userdataobj.type = "hidden";
userdataobj.addBehavior ("#default#userData");
box.appendChild(userdataobj);
//設定物件
var localStorage= {
setItem:function(nam,val)
{userdataobj.load(nam);
userdataobj.setAttribute(nam,val);
var d= new Date();
d.setDate( d.getDate()+700);
userdataobj.expires=d.toUTCString();
userdataobj.save(nam);
userdataobj.load("userdata_record");
var dt=userdataobj.getAttribute("userdata_record");
if(dt==null)dt='';
dt=dt+nam+",";
userdataobj.setAttribute("userdata_record",dt);
userdataobj.save("userdata_record");},
//模擬 setItem
getItem:function(nam)
{userdataobj.load(nam);
return userdataobj.getAttribute(nam); },
//模擬 getItem
removeItem:function(nam)
{userdataobj.load(nam);
clear_userdata(nam)
userdataobj.load("userdata_record");
var dt=userdataobj.getAttribute("userdata_record");
var reg=new RegExp(nam+",","g");
dt=dt.replace(reg,'');
var d= new Date();
d.setDate( d.getDate()+700);
userdataobj.expires= d.toUTCString();
userdataobj.setAttribute("userdata_record",dt);
userdataobj.save("userdata_record");
},
//模擬 removeItem
clear:function(){
userdataobj.load("userdata_record");
var dt=userdataobj.getAttribute("userdata_record").split(",");
for (var i in dt)
{if(dt[i]!='')clear_userdata(dt[i]) }
clear_userdata("userdata_record")
}
//模擬 clear();
}
function clear_userdata(keyname)//將名字為keyname的變數消除
{var keyname;
var d= new Date();
d.setDate( d.getDate()-1);
userdataobj.load(keyname);
userdataobj.expires=d.toUTCString();
userdataobj.save(keyname);
}
}
</script>