详解Vue中localstorage和sessionstorage的使用

1. 项目使用中暴露出来的几个问题

大家到处直接使用localstorage['aaa']='这是一段示例字符串'这些原生语法实现,这样耦合度太高了,假如有一天我们需要换实现方式,或者对存储大小做一些控制,那么需要修改的代码就会很多

项目很大,那么大家起的key的名字难免会重复,而且这样也会造成全局污染

因为localstorage的使用不规范,所以造成了存储空间的浪费和不够用

2. 解决办法

封装storage的使用方法,统一处理

规范storage的key值的命名规则
规范storage的使用规范

2.1. 封装统一的方法

封装成方法可以降低耦合度,可以方便切换实现方式,可以控制存储量大小

改变实现可以通过配置不同的参数来实现

编辑如图所示的项目结构

代码实现

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
/*
  * storage.js
  */
/*
  * @Desc: 本地数据存储方法封装
  * @Ref:
  * @Explain:为了不new对象,只能多写几遍
  * @Example:
  *
  * 1、LocalStorage的使用
  * import storage from '@/utils/storage.js'
  * storage.setItem('shiguoqing0',[1,2,3,4,5,6])
  * storage.setItem('shiguoqing1',{userId:'dfdf',token:11232323})
  * storage.setItem('shiguoqing2','dfdfdf')
  * console.log(storage.getItem('shiguoqing0'))
  * console.log(storage.getItem('shiguoqing1'))
  * console.log(storage.getItem('shiguoqing2'))
  * storage.removeItem('shiguoqing2')
  *
  *
  * 2、SessionStorage的使用
  * storage.setItem('shiguoqing0',[1,2,3,4,5,6],{type:'session'})
  *
  * */
// TODO:其他方法的实现
// TODO:超时时间的设置
/*
  * 方法实现
  * */
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',// local,session,cookies,json
   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(){},
  // 获取最大存储空间:只有LocalStorage和SessionStorage可以使用这个方法
  getMaxSpace(options){
   let store=this.getStorage(options)
   store.getMaxSpace()
  },
  // 获取使用了的空间:只有LocalStorage和SessionStorage可以使用这个方法
  getUsedSpace(options){
   let store=this.getStorage(options)
   store.getUsedSpace()
  }
}
export default storage
// 5、遍历localStorage存储的key
//  .length 数据总量,例:localStorage.length
//  .key(index) 获取key,例:var key=localStorage.key(index);
// 备注:localStorage存数的数据是不能跨浏览器共用的,一个浏览器只能读取各自浏览器的数据,储存空间5M。
// 超时设置
// function(st, key, value, expires) {
//  if (st == 'l') {
//   st = window.localStorage;
//   expires = expires || 60;
//  } else {
//   st = window.sessionStorage;
//   expires = expires || 5;
//  }
//  if (typeof value != 'undefined') {
//   try {
//    return st.setItem(key, JSON.stringify({
//     data: value,
//     expires: new Date().getTime() + expires * 1000 * 60
//    }));
//   } catch (e) {}
//  } else {
//   var result = JSON.parse(st.getItem(key) || '{}');
//   if (result && new Date().getTime() < result.expires) {
//    return result.data;
//   } else {
//    st.removeItem(key);
//    return null;
//   }
//  }
// }
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
/*
  * localstorage.js
  * localstorage的实现
  */
// 这个有点奇怪,文件名称叫local.js不能按照js文件解析
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(){},
  // 获取localstorage最大存储容量
  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)
  },
  // 获取使用了的localstorage的空间
  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')
  }
}
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
/*
  * session.js
  * sessionstorage的实现
  */
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(){},
  // 获取localstorage最大存储容量
  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)
  },
  // 获取使用了的localstorage的空间
  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')
  }
}
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/*
  * cookies.js
  * cooikes的实现,这辈子估计没有时间实现了
  */
export default {
  getItem(key){},
  setItem(key, value){},
  removeItem(key){},
  getAll(){},
  clear(){},
  key(n){},
  forEach(cb){},
  has(key){},
  deleteAllExpires(){}
}
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/*
  * json.js
  * json的实现,这辈子估计也没有时间实现了
  */
export default {
  getItem(key){},
  setItem(key, value){},
  removeItem(key){},
  getAll(){},
  clear(){},
  key(n){},
  forEach(cb){},
  has(key){},
  deleteAllExpires(){}
}

2.2. 规范命名空间的使用

为了防止key值污染,我们可以合理使用命名空间

我们可以定义命名空间,但是不能把很多数据存储在同一对象里面,这样后面的操作量会太大

比如全局的在global下面

比如各功能系统的加上系统词缀

一个系统的命名空间规范应该提前设计好,否则真正开发起来会有很多人不按照规则使用

全局使用的东西要在README.md文档中体现出来

示例

?
1
2
3
4
5
6
7
8
9
* 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. 字符长短获取

?
1
2
3
4
5
6
7
8
var len = 0
for (var i = 0; i < val.length; i++) {
  if (val[i].match(/[^\x00-\xff]/ig) != null) //全角
   len += 2 //如果是全角,占用两个字节 如果mysql中某字段是text, 如果设置编码为utf-8,那么一个中文是占3个字节, gbk是两个字节
  else
   len += 1 //半角占用一个字节
}
return len


猜你喜欢

转载自blog.csdn.net/dx18520548758/article/details/79740077