1. 項目使用中暴露出來的幾個問題
- 大家到處直接使用
這些原生文法實作,這樣耦合度太高了,假如有一天我們需要換實作方式,或者對存儲大小做一些控制,那麼需要修改的代碼就會很多localstorage['aaa']='這是一段示例字元串'
- 項目很大,那麼大家起的key的名字難免會重複,而且這樣也會造成全局污染
- 因為localstorage的使用不規範,是以造成了存儲空間的浪費和不夠用
2. 解決辦法
- 封裝storage的使用方法,統一處理
- 規範storage的key值的命名規則
- 規範storage的使用規範
2.1. 封裝統一的方法
- 封裝成方法可以降低耦合度,可以友善切換實作方式,可以控制存儲量大小
- 改變實作可以通過配置不同的參數來實作
- 編輯如圖所示的項目結構
- 代碼實作
/*
* storage.js
*/
/*
* @Author: 石國慶
* @Desc: 本地資料存儲方法封裝
* @Date: 2017.11.14
* @Ref:
* https://github.com/WQTeam/web-storage-cache
* https://developer.mozilla.org/en-US/docs/Web/API/Storage/LocalStorage
* @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
// https://segmentfault.com/a/1190000002458488
// 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;
// }
// }
// }
/*
* 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')
}
}
/*
* 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')
}
}
/*
* cookies.js
* cooikes的實作,這輩子估計沒有時間實作了
*/
export default {
getItem(key){},
setItem(key, value){},
removeItem(key){},
getAll(){},
clear(){},
key(n){},
forEach(cb){},
has(key){},
deleteAllExpires(){}
}
/*
* 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文檔中展現出來
- 示例
* 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 //如果是全角,占用兩個位元組 如果mysql中某字段是text, 如果設定編碼為utf-8,那麼一個中文是占3個位元組, gbk是兩個位元組
else
len += 1 //半角占用一個位元組
}
return len
4. 參考和引用
- 判斷浏覽器的存儲量還剩多少,判斷浏覽器最大存儲量
- 方法名字可以參考這裡面的
5. 特别感謝
- 公司的小夥伴
6. 免責說明
- 本文檔中的部分内容摘自網上的衆多部落格,僅作為自己知識的補充和整理,并分享給其他需要的coder,不會用于商用。
- 因為很多部落格的位址看完沒有及時做儲存,是以很多不會在這裡标明出處,非常感謝各位大牛的分享,也希望大家了解。
- 如果原文作者感覺不适,可以及時聯系我[email protected],我将及時删除争議部分内容
7. 追責聲明
- 如有大段引用超過全文50%的内容,請在文檔結尾标明原文出處:龍馬行空-石國慶-朱庇特- https://my.oschina.net/u/1416844/blog ,否則将視為抄襲,予以法律追究,請各位尊重個人知識産權。
原文釋出時間為:2017/12/07
原文作者: 龍馬行空
本文來源:
開源中國 https://my.oschina.net/powertoolsteam/blog/1587811如需轉載請聯系原作者