脚本宝典收集整理的这篇文章主要介绍了html5教程-【缓存/性能】HTML5缓存的那些事,脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。小宝典致力于为广大程序猿(媛)提供高品质的代码服务,请大家多多光顾小站,小宝典在此谢过。
更多前端文章:http://lvtraveler.gIThub.io/
说到存储,你可能会想到这是服务器端的一种设置。
服务器端的存储介质大体上分为4种:
cache:缓存,它可以让从数据库、磁盘上输出的东西/数据放置在缓存里,从而减少数据库或是磁盘的读取与写入(IO)操作; 磁盘文件:如,我们常常会将图片、视频等文件存放在磁盘上; 数据库:MySQL/mongoDB…关系/非关系数据库; 内存:通常放置频繁要使用到的东西,能够提高读取效率;缓存(cache)也是存放在内存里的;在HTML5出生之前,通常在浏览器(客户端)使用cookies来存储客户端的内容;
cookies的特点:
每次的http请求头中,都会带有cookies――缺点; 每个域名只能存储4K大小的cookies; 主域名污染:如果我们使用cookies存储主域名的东西,那么子域名下得Http请求都会带上主域名的东西;如果关联上网络,那么将带来安全问题。
所以,通常我们会使用cookies用在如购物车、身份验证等问题上。
下面,我们来看一下百度首页的cookies在浏览器端的一个存储形态:
如图:
HTTP这一列,如果在setCookie的时候,这里就会打钩,这与httponly相关。<"/kf/ware/vc/" target="_blank" class="keylink">vcD4KCjxwPkhUVFBPbmx5o7o8L3A+Cgo8cD7I57n7sNFIVFRQT25secno1sPOqnRydWUsXMfDtGNvb2tpZxpWu8TcsBTzZXJ2ZXK3/s7xxve2y8C0tsHIobvyysfQ3rjEo6y/zbuntsvDu9PQyKjP3r340NC2wcihus3Q3rjEoaPA/cjno6zO0sPh1Nq9+NDQye233dHp1qS1xMqxuvKjrL7Nv8nS1Mq508pv4rj2oam8L3A+Cgo8cD5TZWn1cmWjutPRsLLIq8/gudijrMjnufvJ6NbDwcujrMTHw7TH68fz1rvE3MrHwLTX1EhUVfc808Pcx+vH86GjPC9wPgoKCgo8admgaWQ9"html的存储-userdata">HTML的存储-UserData 只有IE支持,有微软提供API,但不符合W3C标准; 存储在XML文件中;
针对以上问题,HTML5的出现,需要解决以下问题:
解决4K的大小问题; 解决请求头常带存储信息的问题; 解决关系型存储的问题; 跨浏览器平台问题;API:
localstorage 、sessionstorage
存储形式:
keyC>value
过期时间:
localstorage:永久存储,永不失效,除非手动删除
sessionstorage:重新打开页面,或是关闭浏览器,sessionstorage才会消失;
存储大小:
每个域名能存5M;
支持情况:
IE8+,safari3.2+,chrome,firefox等主流浏览器都支持;
使用方法――localstorage/sessionstorage
主要涉及到5个方法:
getItem:获取localstorage/sessionstorage setItem:设置localstorage/sessionstorage removeitem:移除localstorage/sessionstorage key:获取某一个位置上的key值,按值从0开始索引; clear:全部清除localstorage/sessionstorage在控制台Console输出面板,输入:
localStorage.setItem("test1","test");
那么在Resources面板的Local Storage下,将出现Key=test1,value=test的记录
localStorage.getItem("test1");
//输出test
localStorage.key(0);
//输出BDSUGStoreD
sessionstorage的API与localstorage一样,但是你要注意一点:
sessionStorage需要在浏览器关闭或是重新打开页面,才会消失;
只要能被转化为字符串的数据,都能被localstorage存储;
先来看一段代码:
VAR src="demo.jpg"; function set(key){ var img=document.createElement('img'); img.addEventListener("load",function(){ //创建一个canvas var imgCanvas=document.createElement("canvas"), imgContext=imgCanvas.getContext("2d"); //确保canvas元素的大小和图片的尺寸一致 imgCanvas.width=this.width; imgCanvas.height=this.height; //渲染图片到canvas中,使用canvas的drawImage()方法 imgContext.drawImage(this,0,0,this.width,this.height); //用canvas的dataUrl的形式取出图片,imgAsDataURL是一个base64的字符串 var imgAsDataURL=imgCanvas.toDataURL("image/png"); //保存到本地存储中 //使用try-catch()查看是否支持localstorage try{ localStorage.setItem(key,imgAsDataURL);//将取出的图片存放到localStorage } catch(e) { console.LOG("Storage failed:"+e);//存储失败 } },false); img.src=src; } function get(key) {//从本地缓存获取图片并且渲染 var srcStr=localStorage.getItem(key);//从localStorage中取出图片 var imgObj=document.createElement('img');//创建一个img标签 imgObj.src=srcStr; document.body.apPEndChild(imgObj); } 注释: (1)、这个比较适合用在不常更改的图片,但是如果图片的base64大小比较大的话,将比较耗费localStorage的资源; (2)、canvas有一个安全策略的问题:如果图片和你本身请求的域名不在同一个域名下,浏览器会报出一个安全问题,这个时候我们要给我们的服务器加一个“允许跨域”访问的响应头――――Access Orign=*,这样来保证你的图片可进行跨域被canvas来画;
做法:根据前面代码,我们在检查是否支持,先进行setItem()一次,然后对setItem进行异常捕获;
写数据的时候,需要异常处理,避免超出容量抛出错误;
localStorage本身只有5M;
避免把敏感的信息存入localStorage;
key的唯一性;重复写,将会覆盖之前的key;
先来看一下代码:
function set(key,y){ var curTime=new Date().getTime(); //存储一个当时存储时候的时间 localStorage.setItem(key,JSON.stringify({data:v,time:curTime})); } function get(key,exp) { var data=localStorage.getItem(key); var dataObj=JSON.parse(data); if(new Date().getTime()-dataObj.time>exp) {//get出来的时间减去当时存储的时间大于过期时间,那么就认为过期 console.log("过期"); }else { //否则,返回值 console.log("data="+dataObj.data); } }
我们来看一张图,显示的是本地存储和网络拉取耗时的对比:
IndexedDB,是一种能做浏览器中持久地存储结构化数据的数据库,并且为web应用提供了丰富的查询能力;
chrome11+/opera不支持/firefox 4+/IE 10+,移动端浏览器支持能力弱
IndexedDB是按域名分配独立空间,一个独立域名下可以创建多个数据库,每个数据库可以创建对个对象存储空间(表/table),一个对象存储空间可以存储多个对象数据;
如图:
这里我们主要从IndexedDB 的四大功能入手:
增删改 事务处理 游标 索引下面我们通过一段代码来讲解,请关注里面的注释:
<script type="text/javascript"> var db; var arrayKey=[]; var openRequest; var lastCursor; var indexedDB=window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB || window.msIndexedDB;//indexedDB在不同的浏览器下不同 var dbName="person";//数据库名称 var tableName="testTable";//表名称 function init() { openRequest=indexedDB.open(dbName);//页面加载时先打开一个DB,如果该DB存在,则打开;不存在,则新建 //触发事件――当一个“新的数据库”被创建或者数据库的“版本号”被更改时触发 openRequest.onupgradeneeded=function(e){ console.log("onupgradeneeded"); var thisDb=e.target.result; console.log(thisDb.version); //检查这个数据库中是否包含我们要查找的表 if(!thisDb.objectStorenames.contains(tableName)){ //不包含――创建一个表 console.log("需要创建一个objectStore"); //keyPath:主键,autoIncrement:主键自增 var objectStore=thisDb.createObjectStore(tableName,{keyPath:"id",autoIncrement:true}); //创建表的时候,指定哪些字段是能被索引的 objectStore.createIndex("name","name",{unique:false});//创建索引 objectStore.createIndex("phone","phone",{unique:false}); } } //触发事件――成功打开一个数据库时触发 openRequest.onsuccess=function(e){ db=e.target.result; console.log(db.version); db.onerror=function(event){ alert("数据库错误:"+event.target.errorCode); console.dir(event.target); }; //判断该数据库中有没有这个表 if(db.objectStorenames.contains(tableName)){ //存在这个表 console.log("包含表:"+tableName); //通过事物机制操作一个表的读写,从而保证数据的一致性和可靠性 var transaction=db.transaction([tableName],"readwrite"); //事物的事件 transaction.oncomplete=function(event){ console.log("完成"); }; transaction.onerror=function(event){ console.dir(event); }; var objectStore=transaction.objectStore(tableName);//通过事物获取表中一个objectStore对象,即表的对象 //遍历表的记录――游标-openCursor,这是indexedDb的重点 objectStore.openCursor().onsuccess=function(event){ var cursor=event.target.result; if(cursor){ console.log(cursor.key); console.dir(cursor.value); render({key:cursor.key,name:cursor.value["name"],phone:cursor.value["phone"],address:cursor.value["address"]}); lastCursor=cursor.key;//如果不设置lastCursor,那么游标默认是下一条接着下一条来遍历;设置了lastCursor,游标将循环遍历 cursor.continue(); }else { console.log("请使用游标来搞定"); } }; objectStore.openCursor().onerror=function(event){ console.dir(event); }; } } //添加新记录 document.querySelector("#add").addEventListener("click",function(){ var name=document.querySelector("#name").value(); var phone=document.querySelector("#phone").value(); var address=document.querySelector("address").value(); var person={"name":name,"phone":phone,"address":address};//设置对象 //通过事务――操作表 var transaction=db.transaction([tableName],"readwrite"); transaction.oncomplete=function(event){ console.log("事务处理完成"); }; transaction.onerror=function(event){ console.dir(event); }; var objectStore=transaction.objectStore(tableName);//创建一个表对象 objectStore.add(person);//添加对象到表中――add() //将新增的记录显示处理 objectStore.openCursor().onsuccess=function(event){ cursor=event.target.result; var key; if(lastCursor==null){ key=cursor.key; lastCursor=key; }else { key=++lastCursor; } render({key:key,name:name,phone:phone,address:address}); console.log("成功添加新记录:"+key); console.dir(person); } }); //删除指定ID function deleteRecord(id){ var transaction=db.transaction([tableName],"readwrite"); transaction.oncomplete=function(event){ console.log("事务处理完成"); }; transaction.onerror=function(event){ console.dir(event); }; var objectStore=transaction.objectStore(tableName); var removeKey=parseInt(id); var getRequest=objectStore.get(removeKey);//获取索引值---get() getRequest.onsuccess=function(e){ var result=getRequest.result; console.dir(result); } var request=objectStore.delete(removeKey);//删除――delete request.onsuccess=function(e){ console.log("删除成功"); }; request.onerror=function(e){ console.log("删除错误"+e); }; //隐藏删除的DOM document.getElementById(removeKey).style.display="none"; } //查询记录 document.querySelector("#seletBtn").addEventListener("click",function(){ var curName=document.getElementById("selname").value; var transaction=db.transaction([tableName],"readwrite"); transaction.oncomplete=function(event){ console.log("事务处理完成"); }; transaction.onerror=function(event){ console.dir(event); }; var objectStore=transaction.objectStore(tableName); var boundKeyRange=IDBKeyRange.only(curName);//生成一个表示范围的Range对象---iDBKeyRange,有4个方法,only/lowerBound/upperBound/bound objectStore.index("name").openCursor(boundKeyRange).onsuccess=function(event){ //从indexedDb中找到name var cursor=event.target.result; if(!cursor){ return; } var rowData=cursor.value; console.log(rowData); document.getElementById('content').innerHTML=""; render({key:cursor.value.id,name:cursor.value["name"],phone:cursor.value["phone"],address:cursor.value["address"]}); cursor.continue(); }; }); //删除数据库 document.querySelector("#deleteDB").addEventListener("click",function(){ //使用deleteDatabase() var deleteDB=indexedDB.deleteDatabase(dbName); var content=document.querySelector("#content"); while(content.FirstChild){ content.removeChild(content.firstChild); } deleteDB.onsuccess=function(event){ console.log("删除成功"); }; deleteDB.onerror=function(event){ console.dir(event.target); }; }); //渲染 function render(opt){ var child_node = document.createElement("p"); var child_node_child1 = document.createElement("p"); var child_node_child2 = document.createElement("p"); var child_node_child3 = document.createElement("p"); var child_node_child4 = document.createElement("p"); child_node_child1.setattribute("class","table_child"); child_node_child2.setAttribute("class","table_child"); child_node_child3.setAttribute("class","table_child"); child_node_child4.setAttribute("class","table_child"); child_node_child1.setAttribute("style","float:left"); child_node_child2.setAttribute("style","float:left"); child_node_child3.setAttribute("style","float:left"); child_node_child4.setAttribute("style","float:left"); child_node_child1.innerHTML = name; child_node_child2.innerHTML = opt.phone; child_node_child3.innerHTML = opt.address; child_node_child4.innerHTML = "" child_node.appendChild(child_node_child1); child_node.appendChild(child_node_child2); child_node.appendChild(child_node_child3); child_node.appendChild(child_node_child4); child_node.setAttribute("class","table_tr"); child_node.setAttribute("id",opt.key); var content = document.getElementById('content'); content.appendChild(child_node) } } </script>