Web - 客户端存储的几种方式
客户端存储主要方便一些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/