• 售前

  • 售后

热门帖子
入门百科

HTML5中Localstorage的利用教程

[复制链接]
Vonice 显示全部楼层 发表于 2021-10-26 12:44:11 |阅读模式 打印 上一主题 下一主题
什么是localstorage
  前几天在老项目中发现有对cookie的操纵觉得很奇怪,咨询下来是要缓存一些信息,以制止在URL上面传递参数,但没有思量过cookie会带来什么问题:
  ① cookie巨细限制在4k左右,不适合存业务数据
  ② cookie每次随HTTP事件一起发送,浪费带宽
  我们是做移动项目的,所以这里真实适合利用的技能是localstorage,localstorage可以说是对cookie的优化,利用它可以方便在客户端存储数据,而且不会随着HTTP传输,但也不是没有问题:
  ① localstorage巨细限制在500万字符左右,各个浏览器不同等
  ② localstorage在隐私模式下不可读取
  ③ localstorage本质是在读写文件,数据多的话会比力卡(firefox会一次性将数据导入内存,想想就觉得吓人啊)
  ④ localstorage不能被爬虫爬取,不要用它完全取代URL传参
  瑕不掩瑜,以上问题皆可制止,所以我们的关注点应该放在怎样利用localstorage上,而且是怎样精确利用。
localstorage的利用
  基础知识
  localstorage存储对象分为两种:
  ① sessionStrage: session即会话的意思,在这里的session是指用户浏览某个网站时,从进入网站到关闭网站这个时间段,session对象的有用期就只有这么长。
  ② localStorage: 将数据保存在客户端硬件装备上,不管它是什么,意思就是下次打开计算机时候数据还在。
  两者区别就是一个作为临时保存,一个恒久保存。
  这里来一段简单的代码阐明其基本利用:
XML/HTML Code复制内容到剪贴板
       
  • <div id="msg" style="margin: 10px 0; border: 1px solid black; padding: 10px; width: 300px;      
  •   height: 100px;">      
  • </div>      
  • <input type="text" id="text" />      
  • <select id="type">      
  •   <option value="session">sessionStorage</option>      
  •   <option value="local">localStorage</option>      
  • </select>      
  • <button onclick="save();">      
  •   保存数据</button>      
  • <button onclick="load();">      
  •   读取数据</button>      
  • <script type="text/javascript">      
  •   var msg = document.getElementById('msg'),      
  •             text = document.getElementById('text'),      
  •             type = document.getElementById('type');      
  •       
  •   function save() {      
  •     var str = text.value;      
  •     var t = type.value;      
  •     if (t == 'session') {      
  •       sessionStorage.setItem('msg', str);      
  •     } else {      
  •       localStorage.setItem('msg', str);      
  •     }      
  •   }      
  •       
  •   function load() {      
  •     var t = type.value;      
  •     if (t == 'session') {      
  •       msg.innerHTML = sessionStorage.getItem('msg');      
  •     } else {      
  •       msg.innerHTML = localStorage.getItem('msg');      
  •     }      
  •   }      
  • </script>  
 真实场景
  实际工作中对localstorage的利用一般有以下需求:
  ① 缓存一般信息,如搜索页的出发都会,达到都会,非及时定位信息
  ② 缓存都会列表数据,这个数据通常比力大
  ③ 每条缓存信息需要可追踪,好比服务器关照都会数据更新,这个时候在近来一次访问的时候要自动设置逾期
  ④ 每条信息具有逾期日期状态,在逾期外时间需要由服务器拉取数据
XML/HTML Code复制内容到剪贴板
       
  • define([], function () {      
  •       
  •   var Storage = _.inherit({      
  •     //默认属性      
  •     propertys: function () {      
  •       
  •       //署理对象,默以为localstorage      
  •       this.sProxy = window.localStorage;      
  •       
  •       //60 * 60 * 24 * 30 * 1000 ms ==30天      
  •       this.defaultLifeTime = 2592000000;      
  •       
  •       //本地缓存用以存放全部localstorage键值与逾期日期的映射      
  •       this.keyCache = 'SYSTEM_KEY_TIMEOUT_MAP';      
  •       
  •       //当缓存容量已满,每次删除的缓存数      
  •       this.removeNum = 5;      
  •       
  •     },      
  •       
  •     assert: function () {      
  •       if (this.sProxy === null) {      
  •         throw 'not override sProxy property';      
  •       }      
  •     },      
  •       
  •     initialize: function (opts) {      
  •       this.propertys();      
  •       this.assert();      
  •     },      
  •       
  •     /*      
  •     新增localstorage      
  •     数据格式包括唯一键值,json字符串,逾期日期,存入日期      
  •     sign 为格式化后的哀求参数,用于同一哀求不同参数时候返回新数据,好比列表为北京的都会,后切换为上海,会判断tag不同而更新缓存数据,tag相称于署名      
  •     每一键值只会缓存一条信息      
  •     */      
  •     set: function (key, value, timeout, sign) {      
  •       var _d = new Date();      
  •       //存入日期      
  •       var indate = _d.getTime();      
  •       
  •       //终极保存的数据      
  •       var entity = null;      
  •       
  •       if (!timeout) {      
  •         _d.setTime(_d.getTime() + this.defaultLifeTime);      
  •         timeout = _d.getTime();      
  •       }      
  •       
  •       //      
  •       this.setKeyCache(key, timeout);      
  •       entity = this.buildStorageObj(value, indate, timeout, sign);      
  •       
  •       try {      
  •         this.sProxy.setItem(key, JSON.stringify(entity));      
  •         return true;      
  •       } catch (e) {      
  •         //localstorage写满时,全清掉      
  •         if (e.name == 'QuotaExceededError') {      
  •           //            this.sProxy.clear();      
  •           //localstorage写满时,选择离逾期时间近来的数据删除,如许也会有些影响,但是感觉比全扫除好些,假如缓存过多,此过程比力耗时,100ms以内      
  •           if (!this.removeLastCache()) throw '本次数据存储量过大';      
  •           this.set(key, value, timeout, sign);      
  •         }      
  •         console && console.log(e);      
  •       }      
  •       return false;      
  •     },      
  •       
  •     //删除逾期缓存      
  •     removeOverdueCache: function () {      
  •       var tmpObj = null, i, len;      
  •       
  •       var now = new Date().getTime();      
  •       //取出键值对      
  •       var cacheStr = this.sProxy.getItem(this.keyCache);      
  •       var cacheMap = [];      
  •       var newMap = [];      
  •       if (!cacheStr) {      
  •         return;      
  •       }      
  •       
  •       cacheMap = JSON.parse(cacheStr);      
  •       
  •       for (i = 0, len = cacheMap.length; i < len; i++) {      
  •         tmpObj = cacheMap;      
  •         if (tmpObj.timeout < now) {      
  •           this.sProxy.removeItem(tmpObj.key);      
  •         } else {      
  •           newMap.push(tmpObj);      
  •         }      
  •       }      
  •       this.sProxy.setItem(this.keyCache, JSON.stringify(newMap));      
  •       
  •     },      
  •       
  •     removeLastCache: function () {      
  •       var i, len;      
  •       var num = this.removeNum || 5;      
  •       
  •       //取出键值对      
  •       var cacheStr = this.sProxy.getItem(this.keyCache);      
  •       var cacheMap = [];      
  •       var delMap = [];      
  •       
  •       //阐明本次存储过大      
  •       if (!cacheStr) return false;      
  •       
  •       cacheMap.sort(function (a, b) {      
  •         return a.timeout - b.timeout;      
  •       });      
  •       
  •       //删除了哪些数据      
  •       delMap = cacheMap.splice(0, num);      
  •       for (i = 0, len = delMap.length; i < len; i++) {      
  •         this.sProxy.removeItem(delMap.key);      
  •       }      
  •       
  •       this.sProxy.setItem(this.keyCache, JSON.stringify(cacheMap));      
  •       return true;      
  •     },      
  •       
  •     setKeyCache: function (key, timeout) {      
  •       if (!key || !timeout || timeout < new Date().getTime()) return;      
  •       var i, len, tmpObj;      
  •       
  •       //获取当前已经缓存的键值字符串      
  •       var oldstr = this.sProxy.getItem(this.keyCache);      
  •       var oldMap = [];      
  •       //当前key是否已经存在      
  •       var flag = false;      
  •       var obj = {};      
  •       obj.key = key;      
  •       obj.timeout = timeout;      
  •       
  •       if (oldstr) {      
  •         oldMap = JSON.parse(oldstr);      
  •         if (!_.isArray(oldMap)) oldMap = [];      
  •       }      
  •       
  •       for (i = 0, len = oldMap.length; i < len; i++) {      
  •         tmpObj = oldMap;      
  •         if (tmpObj.key == key) {      
  •           oldMap = obj;      
  •           flag = true;      
  •           break;      
  •         }      
  •       }      
  •       if (!flag) oldMap.push(obj);      
  •       //最后将新数组放到缓存中      
  •       this.sProxy.setItem(this.keyCache, JSON.stringify(oldMap));      
  •       
  •     },      
  •       
  •     buildStorageObj: function (value, indate, timeout, sign) {      
  •       var obj = {      
  •         value: value,      
  •         timeout: timeout,      
  •         sign: sign,      
  •         indate: indate      
  •       };      
  •       return obj;      
  •     },      
  •       
  •     get: function (key, sign) {      
  •       var result, now = new Date().getTime();      
  •       try {      
  •         result = this.sProxy.getItem(key);      
  •         if (!result) return null;      
  •         result = JSON.parse(result);      
  •       
  •         //数据逾期      
  •         if (result.timeout < now) return null;      
  •       
  •         //需要验证署名      
  •         if (sign) {      
  •           if (sign === result.sign)      
  •             return result.value;      
  •           return null;      
  •         } else {      
  •           return result.value;      
  •         }      
  •       
  •       } catch (e) {      
  •         console && console.log(e);      
  •       }      
  •       return null;      
  •     },      
  •       
  •     //获取署名      
  •     getSign: function (key) {      
  •       var result, sign = null;      
  •       try {      
  •         result = this.sProxy.getItem(key);      
  •         if (result) {      
  •           result = JSON.parse(result);      
  •           sign = result && result.sign      
  •         }      
  •       } catch (e) {      
  •         console && console.log(e);      
  •       }      
  •       return sign;      
  •     },      
  •       
  •     remove: function (key) {      
  •       return this.sProxy.removeItem(key);      
  •     },      
  •       
  •     clear: function () {      
  •       this.sProxy.clear();      
  •     }      
  •   });      
  •       
  •   Storage.getInstance = function () {      
  •     if (this.instance) {      
  •       return this.instance;      
  •     } else {      
  •       return this.instance = new this();      
  •     }      
  •   };      
  •       
  •   return Storage;      
  •       
  • });  
这段代码包含了localstorage的基本操纵,而且对以上问题做了处理,而真实的利用还要再抽象:

XML/HTML Code复制内容到剪贴板
       
  • define(['AbstractStorage'], function (AbstractStorage) {      
  •       
  •   var Store = _.inherit({      
  •     //默认属性      
  •     propertys: function () {      
  •       
  •       //每个对象肯定要具有存储键,而且不能重复      
  •       this.key = null;      
  •       
  •       //默认一条数据的生命周期,S为秒,M为分,D为天      
  •       this.lifeTime = '30M';      
  •       
  •       //默认返回数据      
  •       //      this.defaultData = null;      
  •       
  •       //署理对象,localstorage对象      
  •       this.sProxy = new AbstractStorage();      
  •       
  •     },      
  •       
  •     setOption: function (options) {      
  •       _.extend(this, options);      
  •     },      
  •       
  •     assert: function () {      
  •       if (this.key === null) {      
  •         throw 'not override key property';      
  •       }      
  •       if (this.sProxy === null) {      
  •         throw 'not override sProxy property';      
  •       }      
  •     },      
  •       
  •     initialize: function (opts) {      
  •       this.propertys();      
  •       this.setOption(opts);      
  •       this.assert();      
  •     },      
  •       
  •     _getLifeTime: function () {      
  •       var timeout = 0;      
  •       var str = this.lifeTime;      
  •       var unit = str.charAt(str.length - 1);      
  •       var num = str.substring(0, str.length - 1);      
  •       var Map = {      
  •         D: 86400,      
  •         H: 3600,      
  •         M: 60,      
  •         S: 1      
  •       };      
  •       if (typeof unit == 'string') {      
  •         unitunit = unit.toUpperCase();      
  •       }      
  •       timeout = num;      
  •       if (unit) timeout = Map[unit];      
  •       
  •       //单位为毫秒      
  •       return num * timeout * 1000 ;      
  •     },      
  •       
  •     //缓存数据      
  •     set: function (value, sign) {      
  •       //获取逾期时间      
  •       var timeout = new Date();      
  •       timeout.setTime(timeout.getTime() + this._getLifeTime());      
  •       this.sProxy.set(this.key, value, timeout.getTime(), sign);      
  •     },      
  •       
  •     //设置单个属性      
  •     setAttr: function (name, value, sign) {      
  •       var key, obj;      
  •       if (_.isObject(name)) {      
  •         for (key in name) {      
  •           if (name.hasOwnProperty(key)) this.setAttr(k, name[k], value);      
  •         }      
  •         return;      
  •       }      
  •       
  •       if (!sign) sign = this.getSign();      
  •       
  •       //获取当前对象      
  •       obj = this.get(sign) || {};      
  •       if (!obj) return;      
  •       obj[name] = value;      
  •       this.set(obj, sign);      
  •       
  •     },      
  •       
  •     getSign: function () {      
  •       return this.sProxy.getSign(this.key);      
  •     },      
  •       
  •     remove: function () {      
  •       this.sProxy.remove(this.key);      
  •     },      
  •       
  •     removeAttr: function (attrName) {      
  •       var obj = this.get() || {};      
  •       if (obj[attrName]) {      
  •         delete obj[attrName];      
  •       }      
  •       this.set(obj);      
  •     },      
  •       
  •     get: function (sign) {      
  •       var result = [], isEmpty = true, a;      
  •       var obj = this.sProxy.get(this.key, sign);      
  •       var type = typeof obj;      
  •       var o = { 'string': true, 'number': true, 'boolean': true };      
  •       if (o[type]) return obj;      
  •       
  •       if (_.isArray(obj)) {      
  •         for (var i = 0, len = obj.length; i < len; i++) {      
  •           result = obj;      
  •         }      
  •       } else if (_.isObject(obj)) {      
  •         result = obj;      
  •       }      
  •       
  •       for (a in result) {      
  •         isEmpty = false;      
  •         break;      
  •       }      
  •       return !isEmpty ? result : null;      
  •     },      
  •       
  •     getAttr: function (attrName, tag) {      
  •       var obj = this.get(tag);      
  •       var attrVal = null;      
  •       if (obj) {      
  •         attrVal = obj[attrName];      
  •       }      
  •       return attrVal;      
  •     }      
  •       
  •   });      
  •       
  •   Store.getInstance = function () {      
  •     if (this.instance) {      
  •       return this.instance;      
  •     } else {      
  •       return this.instance = new this();      
  •     }      
  •   };      
  •       
  •   return Store;      
  • });  
  我们真实利用的时候是利用store这个类操纵localstorage,代码结束简单测试:

 存储完成,以后都不会走哀求,于是本日的代码基本结束 ,最后在android Hybrid中有一后退按钮,此按钮一旦按下会回到上一个页面,这个时候里面的localstorage大概会读取失效!一个简单不靠谱的办理方案是在webapp中参加:
XML/HTML Code复制内容到剪贴板
       
  • window.onunload = function () { };//适合单页应用,不要问我为什么,我也不知道  
 结语
  localstorage是移动开辟必不可少的技能点,需要深入相识,具体业务代码后续会放到git上,有爱好的朋友可以去相识

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x

帖子地址: 

回复

使用道具 举报

分享
推广
火星云矿 | 预约S19Pro,享500抵1000!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

草根技术分享(草根吧)是全球知名中文IT技术交流平台,创建于2021年,包含原创博客、精品问答、职业培训、技术社区、资源下载等产品服务,提供原创、优质、完整内容的专业IT技术开发社区。
  • 官方手机版

  • 微信公众号

  • 商务合作