文档章节

Vue中localstorage和sessionstorage的使用规范

龙马行空
 龙马行空
发布于 2017/12/07 17:53
字数 2206
阅读 406
收藏 29
点赞 0
评论 3

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,不会用于商用。
  • 因为很多博客的地址看完没有及时做保存,所以很多不会在这里标明出处,非常感谢各位大牛的分享,也希望大家理解。
  • 如果原文作者感觉不适,可以及时联系我shiguoqing999@163.com,我将及时删除争议部分内容

7. 追责声明

  • 如有大段引用超过全文50%的内容,请在文档结尾标明原文出处:龙马行空-石国庆-朱庇特-https://my.oschina.net/u/1416844/blog,否则将视为抄袭,予以法律追究,请各位尊重个人知识产权。

© 著作权归作者所有

共有 人打赏支持
龙马行空
粉丝 385
博文 126
码字总数 102118
作品 0
房山
前端工程师
加载中

评论(3)

a
askacoco
很不错
龙马行空
龙马行空

引用来自“zqq90”的评论

对于判断是字符串还是对象这一点, 我觉得可以加一个单字符前缀表示类型, s 表示 string , j 表示 json, n 表示 null, u 表示 undefined, 等等
恩,能给出一个加在哪里的实现吗?我加进博客中去
zqq90
zqq90
对于判断是字符串还是对象这一点, 我觉得可以加一个单字符前缀表示类型, s 表示 string , j 表示 json, n 表示 null, u 表示 undefined, 等等
WEB前端开发学习HTML5到底有多厉害?

Web前端开发工程师是一个很新的职业,是从事Web前端开发工作的工程师。主要进行网站开发,优化,完善的工作。网页制作是Web 1.0时代的产物,那时网站的主要内容都是静态的,用户使用网站的行...

web前端小辰 ⋅ 05/23 ⋅ 0

mpvue: vuejs和小程序碰撞出来的火花

微信自推出小程序以来,热度一直居高不下,各大公司开始专门开发小程序,但是小程序自定义的wxml和wxss和自己定义的语法,让被三大框架统治的前端江湖头疼不易,因为需要专门为小程序开发一...

蜗牛老湿 ⋅ 05/18 ⋅ 0

CKeditor的爬坑之旅:vue项目下选择媒体库图片

最近在用vue写项目的管理后台,由于是电商+cms项目,所以我们开发了媒体库来管理所有的素材,但是问题来了,在发布文章的时候,我是用了开源的ckeditor,原来带的选择图片上传插件,只能自定...

unfind ⋅ 05/19 ⋅ 0

VeeValidate在vue项目里表单校验应用案例

VeeValidate是什么: VeeValidate是Vue.js的验证库,它有很多验证规则,并支持自定义规则。它基于模板,因此它与HTML5验证API相似并且很熟悉。您可以验证HTML5输入以及自定义Vue组件。它也是...

codercao ⋅ 05/08 ⋅ 0

前端路由简介以及vue-router实现原理

后端路由简介 路由这个概念最先是后端出现的。在以前用模板引擎开发页面时,经常会看到这样 大致流程可以看成这样: 浏览器发出请求 服务器监听到80端口(或443)有请求过来,并解析url路径 ...

muwoo ⋅ 06/01 ⋅ 0

Vue和React数据绑定对比

在数据绑定上来说,vue的特色是双向数据绑定,而在react中是单向数据绑定。 一 单向和双向数据绑定其实不是完全没关系的 表单的双向绑定,说到底不过是 (value 的单向绑定 + onChange 事件侦...

pattyzzh ⋅ 05/14 ⋅ 0

WEB前端学习面试常见问题系列:H5有哪些新标签?

Web前端开发工程师是一个很新的职业,是从事Web前端开发工作的工程师。主要进行网站开发,优化,完善的工作。网页制作是Web 1.0时代的产物,那时网站的主要内容都是静态的,用户使用网站的行...

web前端小辰 ⋅ 05/13 ⋅ 0

WEB前端学习:vue图标组件Vue-Awesome,让你快速方便的使用font-awesome图标

Web前端开发工程师是一个很新的职业,是从事Web前端开发工作的工程师。主要进行网站开发,优化,完善的工作。网页制作是Web 1.0时代的产物,那时网站的主要内容都是静态的,用户使用网站的行...

web前端小辰 ⋅ 06/04 ⋅ 0

记一次小坑--关于window.open()

今天在公司的后台项目中遇到一个这样的需求:点击一个按钮,发送一个请求,然后用请求到的中的打开一个新窗口(跳转到另一个后台)。看起来应该没什么问题,很快代码写好了(vue项目,以下是...

nikolausliu ⋅ 05/11 ⋅ 0

HTML5学习之Web Storage基础知识

HTML5 Web 存储 在HTML5 Web Storage还没出来之前,本地存储使用的是 cookie. 但是Web 存储需要更加的安全与快速,这些数据不会被保存在服务器上,但是这些数据只用于用户请求网站数据上.它也可...

CHIEMINCHAN ⋅ 05/11 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

个人博客的运营模式能否学习TMALL天猫质量为上?

心情随笔|个人博客的运营模式能否学习TMALL天猫质量为上? 中国的互联网已经发展了很多年了,记得在十年前,个人博客十分流行,大量的人都在写博客,而且质量还不错,很多高质量的文章都是在...

原创小博客 ⋅ 今天 ⋅ 0

JavaScript零基础入门——(十一)JavaScript的DOM操作

JavaScript零基础入门——(十一)JavaScript的DOM操作 大家好,欢迎回到我们的JavaScript零基础入门。最近有些同学问我说,我讲的的比书上的精简不少。其实呢,我主要讲的是我在开发中经常会...

JandenMa ⋅ 今天 ⋅ 0

volatile和synchronized的区别

volatile和synchronized的区别 在讲这个之前需要先了解下JMM(Java memory Model :java内存模型):并发过程中如何处理可见性、原子性、有序性的问题--建立JMM模型 详情请看:https://baike.b...

MarinJ_Shao ⋅ 今天 ⋅ 0

深入分析Kubernetes Critical Pod(一)

Author: xidianwangtao@gmail.com 摘要:大家在部署Kubernetes集群AddOn组件的时候,经常会看到Annotation scheduler.alpha.kubernetes.io/critical-pod"="",以表示这是一个关键服务,那你知...

WaltonWang ⋅ 今天 ⋅ 0

原子性 - synchronized关键词

原子性概念 原子性提供了程序的互斥操作,同一时刻只能有一个线程能对某块代码进行操作。 原子性的实现方式 在jdk中,原子性的实现方式主要分为: synchronized:关键词,它依赖于JVM,保证了同...

dotleo ⋅ 今天 ⋅ 0

【2018.06.22学习笔记】【linux高级知识 14.4-15.3】

14.4 exportfs命令 14.5 NFS客户端问题 15.1 FTP介绍 15.2/15.3 使用vsftpd搭建ftp

lgsxp ⋅ 今天 ⋅ 0

JeeSite 4.0 功能权限管理基础(Shiro)

Shiro是Apache的一个开源框架,是一个权限管理的框架,实现用户认证、用户授权等。 只要有用户参与一般都要有权限管理,权限管理实现对用户访问系统的控制,按照安全规则或者安全策略控制用户...

ThinkGem ⋅ 昨天 ⋅ 0

python f-string 字符串格式化

主要内容 从Python 3.6开始,f-string是格式化字符串的一种很好的新方法。与其他格式化方式相比,它们不仅更易读,更简洁,不易出错,而且速度更快! 在本文的最后,您将了解如何以及为什么今...

阿豪boy ⋅ 昨天 ⋅ 0

Python实现自动登录站点

如果我们想要实现自动登录,那么我们就需要能够驱动浏览器(比如谷歌浏览器)来实现操作,ChromeDriver 刚好能够帮助我们这一点(非谷歌浏览器的驱动有所不同)。 一、确认软件版本 首先我们...

blackfoxya ⋅ 昨天 ⋅ 0

线性回归原理和实现基本认识

一:介绍 定义:线性回归在假设特证满足线性关系,根据给定的训练数据训练一个模型,并用此模型进行预测。为了了解这个定义,我们先举个简单的例子;我们假设一个线性方程 Y=2x+1, x变量为商...

wangxuwei ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部