覽器緩衝是很重要的,一次互動,有95%以上的時間是在處理前端的,如果能提高前端的效能,對提高整個系統的效能是很有協助的。本專題主要講的是如何更好地使用瀏覽器緩衝,同時包括了一些今後瀏覽器緩衝的發展趨勢,如:globalStorage等。
影響瀏覽器本機快取的因素及解決方案
因素:子網域名稱
具體描述:berg.sharej.com/img/123.gif 這個圖片,如果按照 sharej.com/berg/img/123.gif這樣的方式訪問,需要重新載入一次。類似的,大小寫不同也會造成重複下載
解決辦法:統一使用一個地址可避免重複下載。
因素:Meta頭
具體描述:<META HTTP-EQUIV="Pragma" CONTENT="no-cache">或者使用指令碼輸出了要求瀏覽器不緩衝網頁的header
解決方案:合理的按照需求使用。
因素:Firefox的cache機制
具體描述:即使是應用了no-cache 頭,firefox還是要先cache ,再根據到期設定決定是否使用。via
解決方案:一般無需解決。因為firefox緩衝這些檔案只是用作前進/後退。
因素:隨機檔案名稱
具體描述:可使用abc.js? 2007120來使瀏覽器重新載入js檔案。一種更安全的方是abc_v071201.js來使瀏覽器重載入(可通過地址修正實現)。
解決方案:在js、css檔案升級後,必要時可進行此處理,避免使用者瀏覽器緩衝的舊的檔案。
因素:innerHTML
具體描述:IE6在window.onload中用innerHTML動態插入圖片的時候會忽略Cache策略,一次載入多張相同圖片時,會重複請求。
解決方案:避免在window.onload中使用innerHTML插入圖片。
因素:IE6無法緩衝背景圖片的bug
具體描述:IE6的 ““temporay internet files”設定為“每次訪問此頁時檢查”時, 背景圖片將無法被緩衝,在滑鼠滑過連結背景圖片更換時,會產生閃爍。
解決方案:document.execCommand("BackgroundImageCache", false, true);在ie6下執行這條語句即可,Firefox執行時會報錯(可用try-cache解決)。用expression也可以達到這個效果最好是用CSS Sprites解決問題。
在瀏覽器端預先緩衝圖片的實現
使用Image()對象緩衝
使用JavaScript建立一個新的Image()對象,然後將希望預裝載的圖片URL傳遞給此對象。通過onLoad()事件控制代碼同步裝載到頁面上。demo
通過數組(arrays)緩衝多個圖片
定義了變數i以及名為imageObj的Image()對象。然後定義了新數組images[],每一個數組元素將儲存需要預裝載圖片的地址來源。最後,使用一個for()迴圈來遍曆整個數組,並對每個元素指定Image()對象,以此將圖片都預裝載到緩衝中。
demo
上面這兩種方法都需要瀏覽器支援javascript才能正常緩衝。
使用CSS隱藏需要緩衝的圖片
採用css的display:none;屬性來隱藏圖片。
demo
使用css中的背景圖片
可以為一個元素定義背景樣式,然後將背景圖片移到不可見的位置。IE6在““temporay internet files”設定為“每次訪問此頁時檢查”時無效。
demo
上面這兩種方法都需要瀏覽器正常解釋css才能正常使用
相簿中圖片的預先載入
上面提到了四種預先緩衝圖片的方法,個人感覺第二種方法最好。因為使用第二種方法可以方便的控制載入的時間,不會影響之前頁面的開啟速度,而且只要支援js的瀏覽器都能正常使用。
demo
這個例子比較簡單,但是已經能實現預先載入了,在開啟縮圖頁面時,只要開啟了緩衝的瀏覽器,大圖就會在頁面結束後逐一被載入。但是一些具體的載入策略還沒有做考慮。
滑鼠滑過背景圖的切換
如前所述,IE6的 “temporay internet files”設定為“每次訪問此頁時檢查”時, 背景圖片將無法被緩衝,在滑鼠滑過連結時(不管是否有背景圖切換),會產生閃爍。其他瀏覽器都能很好的通過超連結的hover來設定背景圖片實現滑鼠滑過,背景圖切換。
IE6閃爍的原因
首先總結ie6中發生閃爍的原因,最後給出一個解決方案。
定義一個這樣的樣式:
.Example a{
background-image:url(some image);
}
下面是所有會引發閃爍的原因:
Background
當此元素background被設定成以下的值時,會發生閃爍:
background-color: transparent
background-repeat: repeat
background-position: 只要設定了都會閃爍
元素的面積
需要這個元素不閃爍,這個元素的面積必須要大於2500px^2。 =。=
.example a {
width: 50px;
height: 50px;
background-image:url(some image);
}
.example a {
width: 50px;
height: 40px;
background-image:url(some image);
}
上面一個樣式不會閃爍而下面一個樣式會閃爍……
圖片是否透明gif
當背景圖片是一個帶透明效果gif時,會閃爍。
跨瀏覽器的解決辦法
<script>
try {
document.execCommand('BackgroundImageCache', false, true);
} catch(e) {}
</script>
<style>
a{ background:transparent url(logo.gif) no-repeat scroll left bottom;line-height:300px;padding:30px;}
a:hover{ background-position:-2000px 100%;}
</style>
<a href="/"> </a>
其中logo為一個包含原圖和翻轉圖片的大圖片。在IE6,IE7,firefox2.0,opear9下測試通過
IE中的userdata的使用
Cookies也能達到在用戶端快取資料的作用,但是cookies的大小限制很嚴格(4K),所以不能用來緩衝過多的使用者資料, userdata的出現解決了這個問題。每個網頁的UserData儲存區資料大小可以達到64 Kb,每個網域名稱可以達到640 Kb。
IE 5以上的IE瀏覽器才支援userdata這個行為。在使用者機器上,userdata預設是儲存在這個位置:C:Documents and Settingsyour login nameApplication DataMicrosoftInternet ExplorerUserData
userData行為通過sessions為每個對象分配UserData儲存區。使用save和load方法將UserData儲存區資料儲存在緩衝 (cache)中。一旦UserData儲存區儲存以後,即使IE瀏覽器關閉或者重新整理了,下一次進入該頁面,資料也能夠重新載入而不會丟失。
在HTML、HEAD、TITLE和STYLE標記上應用了userData行為後使用save和load方法將會出錯。
使用前,必須先聲明樣式:
或者使用指令碼綁定:
object.style.behavior = "url('#default#userData')"
object.addBehavior ("#default#userData")
csdn中列有userdata成員和方法表。
demo
Userdata 的範圍問題
當我在/forum/a這個頁面中執行一次u.Save("sss", "just a forum", 365, "forum");後,userdata的目錄下出現了一個sss[1].xml檔案,內容是:
同時,在/forum/b這個頁面中執行alert(u.Load("sss", "forum"));時,能夠取到userdata中的內容。 而在“/”這個頁面中是取不到剛才存放進去的內容的,同樣的,在“/topic/1234”也是取不到內容的。
類似的,執行u.Save("forum", "just a forum", 365, "value");後再alert的結果和上面的結果相同。
個人覺得userdata和cookies一樣,是和path相關的。同一目錄下的所有頁面能共用同一個檔案中的同一屬性(Attribute)。因此在使用的時候要注意目錄結構的問題。
Userdata的逾時設定
Expires這個屬性是用來設定userdata的逾時時間的。Userdata的逾時設定是針對一個檔案的,一旦到期,整個檔案都到期了,不能單獨設定每個屬性的到期時間。
其他問題
如果 userdata被人為刪除,此時執行o.getAttribute()、o. setAttribute()會報錯:“Error:資料無效。”在使用這兩個方法之前, try-catch o.load()可以屏蔽這個錯誤,但是userdata就無法正常使用了,除非修改儲存的檔案名稱。
刪除userdata的時候不能像刪除cookie一樣,用new Date(0)來製造到期時間。315532799000 是格林威治時間1979年12月31日23時59分59秒。這是刪除UserData的最靠前的一個有效expires時間了。
如果在一個瀏覽器進程中重複刪除、寫入userdata資料,userdata空間將很快被撐滿,因為每次刪除都是邏輯刪除,等到瀏覽器進程結束後才會真正執行刪除操作。
非IE瀏覽器“userdata”的解決方案
sessionStorage
從firefox 2.0開始,開始支援HTML5,同時也就支援了sessionStorage,這是一個只能在session生命週期內使用的對象,最大的用途在於用於儲存一些臨時的資料防止使用者意外重新整理頁面,同時,在瀏覽器意外關閉並恢複頁面時,sessionStrorage中儲存的資訊也會被同時恢複。Firefox預設允許一個網域名稱儲存5120KB的資料。
demo(必須要上傳到伺服器上才能正常運行)
下面是HTML5定義的介面:
interface Storage {
readonly attribute unsigned long length;
DOMString key(in unsigned long index);
DOMString getItem(in DOMString key);
void setItem(in DOMString key, in DOMString data);
void removeItem(in DOMString key);
};
範圍問題
Firefox中的sessionStorage在網域名稱下任意頁面儲存後,整個網域名稱下都可以使用儲存的項目。
其他問題
在瀏覽器crash後,restore頁面的session也不見了,(firefox2.0) 。
globalStorage
這個也是html5中提出來,在瀏覽器關閉以後,使用globalStorage儲存的資訊仍能夠保留下來,並且儲存容量比IE的userdata大得多,一個域下面是5120k。和sessionStorage一樣,域中任何一個頁面儲存的資訊都能被所有的頁面共用。
範圍
globalStorage['z.baidu.com'] 所有z.baidu.com下面的頁面都可以使用這塊空間
globalStorage['baidu.com'] 所有baidu.com下面的頁面都可以使用這塊空間
globalStorage['com']:所有com網域名稱都可以 共用的使用這一塊空間
globalStorage[''] :所有頁面都可以使用的空間
現在Firefox只支援當前域下的globalStorage儲存, 如果使用公用域會導致一個這樣一個類似的錯誤“Security error" code: "1000”。
到期時間
按照HTML5的描述,globalStorage只在安全問題或者當使用者要求時才會到期,瀏覽器應該避免刪除那些正在被指令碼訪問的資料,並且userdata應該是使用者可寫的。
因此我們的指令碼要能夠控制到期時間,可以在globalStorage的某個地區儲存到期時間,在load的時候判斷是否到期,可以在一定程度上解決到期時間的問題。
儲存時,同時儲存到期時間
Save = function(content, expires, attribute, fileName){
var date = new Date();
date.setSeconds(date.getSeconds() + expires);
globalStorage[domain][fileName + "__expires"] = date.getTime();
}
Load時判斷是否到期,到期則刪除:
Load = function(attribute, fileName){
var date = new Date();
if(parseInt(globalStorage[domain][fileName + "__expires"]) < parseInt(date.getTime()) ){
d.Remove(attribute, fileName);
d.Remove(attribute, fileName + "__expires");
}
return globalStorage[domain][fileName + attribute];
}