客戶端存儲主要方便一些APP離線使用。今天就來說說客戶端存儲的方法有多少?
說在最前面的一句:所有的客戶端存儲都有一個原則:讀寫的數據必須要同域
1 Cookie
Cookie是一項很老的技術的,就是因為它老,所以兼容性還是不錯的。常見的JS操作Cookie的代碼如下:
function setCookie(c_name,value,expiredays)
{
var exdate=new Date()
exdate.setDate(exdate.getDate()+expiredays)
document.cookie=c_name+ "=" +escape(value)+((expiredays==null) ? "" : ";expires="+exdate.toGMTString())
}
function getCookie(c_name)
{
if (document.cookie.length>0)
{
c_start=document.cookie.indexOf(c_name + "=")
if (c_start!=-1)
{
c_start=c_start + c_name.length+1
c_end=document.cookie.indexOf(";",c_start)
if (c_end==-1) c_end=document.cookie.length
return unescape(document.cookie.substring(c_start,c_end))
}
}
return ""
}
代碼是從W3school那里扣過來的,大半夜了我也就不知道寫了,請原諒我。
使用Cookie作為本地存儲優點:兼容性好,缺點:操作繁瑣,只能存簡單的數據,還會過期,站點設置httponly的話,JS就不無法操作Cookie了。
2 Web Storage
WebStorage是HTML5中為WebApplication提供一種存儲的API,目前主流的新版本的瀏覽器都支持,當然IE789你就沒有辦法了。WebStorage主要分成localStorage和sessionStorage兩種。
sessionStorage 是個全局對象,它維護着在頁面會話(page session)期間有效的存儲空間。只要瀏覽器開着,頁面會話周期就會一直持續。當頁面重新載入(reload)或者被恢復(restores)時,頁面會話也是一直存在的。每在新標簽或者新窗口中打開一個新頁面,都會初始化一個新的會話。
localStorage也是一個全局變量,它的生命周期比sessionStorage長。localStorage和sessionStorage都繼承自Storage因此它們的用法相同。
interface Storage {
readonly attribute unsigned long length;
[IndexGetter] DOMString key(in unsigned long index);
[NameGetter] DOMString getItem(in DOMString key);
[NameSetter] void setItem(in DOMString key, in DOMString data);
[NameDeleter] void removeItem(in DOMString key);
void clear();
};
// 保存數據到當前會話的存儲空間
sessionStorage.setItem("username", "John");
// 訪問數據
alert( "username = " + sessionStorage.getItem("username"));
WebStorage的優點:使用簡單方便,缺點:IE有些版本不支持,不能存復雜的對象,必須先轉化成JSON字符串,沒有索引搜索效率不高,只能同步讀寫操作,當寫入的數據比較大時可能造成JS引擎堵塞。
3 IndexedDB
IndexedDB是一種基於Javascript對象繼承的數據庫,它支持事務,同時支持異步和同步讀寫。IndexedDB中可以存入對象,當然對象要能夠結構化克隆(structured clone),同時它還提供索引功能,極大地提高了搜索的效率。通常來說IndexedDB的大小是沒有限制,當大小超過50MB的時候,瀏覽器會彈出對話框來詢問用戶是否增加數據的大小。
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);
}
};
var kids = [
{ name: "Anna" },
{ name: "Betty" },
{ name: "Christine" }
];
var request = window.indexedDB.open("CandyDB",
"My candy store database");
request.onsuccess = function(event) {
var objectStore = event.result.objectStore("kids");
for (var index = 0; index < kids.length; index++) {
var kid = kids[index];
objectStore.add(kid).onsuccess = function(event) {
document.getElementById("display").textContent =
"Saved record for " + kid.name + " with id " + event.result;
};
}
};
優點:支持事務,支持索引,可以存入對象,效率也不錯。缺點:使用有些麻煩,上手需要一定時間。
4 FileAPI
在最新版的MDN和w3c中FileAPI相關的文檔只看到了FileReader相關介紹,這個API可以結合File表單和Formdata 從而實現異步上傳文件。因為沒有FileWriter相關文檔說明,我們這里暫時認為FileAPI不能實現客戶端存儲這個要求。
function startRead() {
// obtain input element through DOM
var file = document.getElementById('file').files[0];
if(file){
getAsText(file);
}
}
function getAsText(readFile) {
var reader = new FileReader();
// Read file into memory as UTF-16
reader.readAsText(readFile, "UTF-16");
// Handle progress, success, and errors
reader.onprogress = updateProgress;
reader.onload = loaded;
reader.onerror = errorHandler;
}
function updateProgress(evt) {
if (evt.lengthComputable) {
// evt.loaded and evt.total are ProgressEvent properties
var loaded = (evt.loaded / evt.total);
if (loaded < 1) {
// Increase the prog bar length
// style.width = (loaded * 200) + "px";
}
}
}
function loaded(evt) {
// Obtain the read file data
var fileString = evt.target.result;
// Handle UTF-16 file dump
if(utils.regexp.isChinese(fileString)) {
//Chinese Characters + Name validation
}
else {
// run other charset test
}
// xhr.send(fileString)
}
function errorHandler(evt) {
if(evt.target.error.name == "NotReadableError") {
// The file could not be read
}
}
5 參考
- https://developer.mozilla.org/zh-CN/docs/Web/Guide/API/DOM/Storage/Storage
- https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API
- https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/The_structured_clone_algorithm
- https://developer.mozilla.org/en-US/docs/Web/API/FileReader
- http://www.w3.org/TR/FileAPI/
- http://www.w3.org/TR/file-writer-api/
