1. 项目使用中暴露出来的几个问题
- 大家到处直接使用
localstorage['aaa']='这是一段示例字符串'
这些原生语法实现,这样耦合度太高了,假如有一天我们需要换实现方式,或者对存储大小做一些控制,那么需要修改的代码就会很多
- 项目很大,那么大家起的key的名字难免会重复,而且这样也会造成全局污染
- 因为localstorage的使用不规范,所以造成了存储空间的浪费和不够用
2. 解决办法
- 封装storage的使用方法,统一处理
- 规范storage的key值的命名规则
- 规范storage的使用规范
2.1. 封装统一的方法
- 封装成方法可以降低耦合度,可以方便切换实现方式,可以控制存储量大小
- 改变实现可以通过配置不同的参数来实现
- 编辑如图所示的项目结构
import local from './storage/localstorage.js'
import session from './storage/session.js'
import cookies from './storage/cookies.js'
import json from './storage/json.js'
let storage= {
config:{
type:'local',
expires:new Date().getTime() + 100 * 24 * 60 * 60 * 1000
},
getStorage(options){
let config={}
if(options){
config=Object.assign({},this.config,options)
}else{
config=this.config
}
return this.createStorage(config.type)
},
createStorage(name){
switch(name){
case 'local':return local;break
case 'session':return session;break
case 'cookies':return cookies;break
case 'json':return json;break
}
},
getItem(key,options){
let store=this.getStorage(options)
return store.getItem(key)
},
setItem(key, value,options){
let store=this.getStorage(options)
store.setItem(key,value)
},
removeItem(key,options){
let store=this.getStorage(options)
store.removeItem(key)
},
getAll(){},
clear(options){
let store=this.getStorage(options)
store.clear()
},
key(n){},
lenght(){},
has(key){},
forEach(cb){},
deleteAllExpires(){},
getMaxSpace(options){
let store=this.getStorage(options)
store.getMaxSpace()
},
getUsedSpace(options){
let store=this.getStorage(options)
store.getUsedSpace()
}
}
export default storage
export default {
getItem(key){
let item = localStorage.getItem(key)
let result = /^[{\[].*[}\]]$/g.test(item)
if (result) {
return JSON.parse(item)
} else {
return item
}
},
setItem(key, value){
if (typeof value == "string") {
localStorage.setItem(key, value)
} else {
let item = JSON.stringify(value)
localStorage.setItem(key, item)
}
},
removeItem(key){
localStorage.removeItem(key)
},
getAll(){},
clear(){
localStorage.clear()
},
key(n){},
forEach(cb){},
has(key){},
deleteAllExpires(){},
getMaxSpace(){
if (!window.localStorage) {
console.log('当前浏览器不支持localStorage!')
}
var test = '0123456789'
var add = function (num) {
num += num
if (num.length == 10240) {
test = num
return
}
add(num)
}
add(test)
var sum = test
var show = setInterval(function () {
sum += test
try {
window.localStorage.removeItem('test')
window.localStorage.setItem('test', sum)
console.log(sum.length / 1024 + 'KB')
} catch (e) {
console.log(sum.length / 1024 + 'KB超出最大限制')
clearInterval(show)
}
}, 0.1)
},
getUsedSpace(){
if (!window.localStorage) {
console.log('浏览器不支持localStorage')
}
var size = 0
for (item in window.localStorage) {
if (window.localStorage.hasOwnProperty(item)) {
size += window.localStorage.getItem(item).length
}
}
console.log('当前localStorage使用容量为' + (size / 1024).toFixed(2) + 'KB')
}
}
export default {
getItem(key){
let item = sessionStorage.getItem(key)
let result = /^[{\[].*[}\]]$/g.test(item)
if (result) {
return JSON.parse(item)
} else {
return item
}
},
setItem(key, value){
if (typeof value == "string") {
sessionStorage.setItem(key, value)
} else {
let item = JSON.stringify(value)
sessionStorage.setItem(key, item)
}
},
removeItem(key){
sessionStorage.removeItem(key)
},
getAll(){},
clear(){
sessionStorage.clear()
},
key(n){},
forEach(cb){},
has(key){},
deleteAllExpires(){},
getMaxSpace(){
if (!window.sessionStorage) {
console.log('当前浏览器不支持sessionStorage!')
}
var test = '0123456789'
var add = function (num) {
num += num
if (num.length == 10240) {
test = num
return
}
add(num)
}
add(test)
var sum = test
var show = setInterval(function () {
sum += test
try {
window.sessionStorage.removeItem('test')
window.sessionStorage.setItem('test', sum)
console.log(sum.length / 1024 + 'KB')
} catch (e) {
console.log(sum.length / 1024 + 'KB超出最大限制')
clearInterval(show)
}
}, 0.1)
},
getUsedSpace(){
if (!window.sessionStorage) {
console.log('浏览器不支持sessionStorage')
}
var size = 0
for (item in window.sessionStorage) {
if (window.sessionStorage.hasOwnProperty(item)) {
size += window.sessionStorage.getItem(item).length
}
}
console.log('当前sessionStorage使用容量为' + (size / 1024).toFixed(2) + 'KB')
}
}
export default {
getItem(key){},
setItem(key, value){},
removeItem(key){},
getAll(){},
clear(){},
key(n){},
forEach(cb){},
has(key){},
deleteAllExpires(){}
}
export default {
getItem(key){},
setItem(key, value){},
removeItem(key){},
getAll(){},
clear(){},
key(n){},
forEach(cb){},
has(key){},
deleteAllExpires(){}
}
2.2. 规范命名空间的使用
- 为了防止key值污染,我们可以合理使用命名空间
- 我们可以定义命名空间,但是不能把很多数据存储在同一对象里面,这样后面的操作量会太大
- 比如全局的在global下面
- 比如各功能系统的加上系统词缀
- 一个系统的命名空间规范应该提前设计好,否则真正开发起来会有很多人不按照规则使用
- 全局使用的东西要在README.md文档中体现出来
- 示例
* localStorage['SGQ.global.userAuthor']:登录的用户信息都在这里,菜单,组织,集团
* localStorage['SGQ.global.systemName']:登录的系统名称
* localStorage['SGQ.vuex.state']:vuex中的state的存储地址,这里面有所有的的东西
* localStorage['SGQ.wms.warehouse']:wms需要的仓库信息
+ localStorage['SGQ.wms.warehouse'].permissionId
+ localStorage['SGQ.wms.warehouse'].dataResource
* localStorage['SGQ.tms.org']:tms需要的网点的信息
+ localStorage['SGQ.tms.org'].permissionId
+ localStorage['SGQ.tms.org'].orgName
2.3. storage使用规范
2.3.1. 问题产生的原因
- 这个问题的产生是因为我们要做权限登录,然后登录的时候一直报存储空间不够的问题,查了原因发现是后端把所有的超管的几千条数据都返回来了,以至于不够用,后来修改了后端接口返回的数据内容解决了这个问题。
- 但是这次的事给我们带来了几点思考?
- localstorage和sessionstorage的存储量在不同的浏览器中基本是5M
- localstorage和sessionstorage的存储是跟着域名来的
- boss.hivescm.com下localstorage存储是5M
- b2b.hivescm.com下localstorage存储也是5M
- 即使这次问题解决了,但是我们应该定一套方案,充分利用一个域名下,localstorage和sessionstorage的共10M空间
2.3.2. storage使用方案
- 全局使用的东西,共享的东西,永久存储的东西储存在localstorage中
- 不需要永久存储的东西在使用完毕之后要记得及时清除
- 如果数据量过大就不要存储在本地了,变为动态获取
- 可以使用存储量更大的Indexeddb,不过有兼容性问题
- 可以在实现方案中对要存储到storage中的东西做字数限制
- 充分合理利用sessionstorage和localstorage的H5特性
- 例如:列表数据存储在vuex中其实也会存到localstorage
- 例如:表单校验的一些数据都用sessionstorage
3. 其他
3.1. 延伸扩展
- 由此可以类推到事件的处理,没用的事件要及时在退出vue组件的时候清理掉
- 例如:
this.bus.$on('aa')
要用this.bus.$off('aa')
卸载事件
3.2. 字符长短获取
var len = 0
for (var i = 0; i < val.length; i++) {
if (val[i].match(/[^\x00-\xff]/ig) != null)
len += 2
else
len += 1
}
return len
4. 参考和引用
- 判断浏览器的存储量还剩多少,判断浏览器最大存储量
- 方法名字可以参考这里面的
5. 特别感谢
6. 免责说明
- 本文档中的部分内容摘自网上的众多博客,仅作为自己知识的补充和整理,并分享给其他需要的coder,不会用于商用。
- 因为很多博客的地址看完没有及时做保存,所以很多不会在这里标明出处,非常感谢各位大牛的分享,也希望大家理解。
- 如果原文作者感觉不适,可以及时联系我shiguoqing999@163.com,我将及时删除争议部分内容
7. 追责声明
原文发布时间为:2017/12/07
原文作者:
龙马行空
本文来源:
开源中国
如需转载请联系原作者