Vue中localstorage和sessionstorage的使用規範

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:
 *
 * 一、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')
 *
 *
 * 二、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
// 五、遍歷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,不會用於商用。
  • 由於不少博客的地址看完沒有及時作保存,因此不少不會在這裏標明出處,很是感謝各位大牛的分享,也但願你們理解。
  • 若是原文做者感受不適,能夠及時聯繫我shiguoqing999@163.com,我將及時刪除爭議部份內容

7. 追責聲明

  • 若有大段引用超過全文50%的內容,請在文檔結尾標明原文出處:龍馬行空-石國慶-朱庇特-https://my.oschina.net/u/1416844/blog,不然將視爲抄襲,予以法律追究,請各位尊重我的知識產權。
相關文章
相關標籤/搜索