当前位置: 首页 > Web前端 > HTML5

关于网页本地存储的一些思考

时间:2023-04-05 21:26:07 HTML5

前言localStoragesessionStorage等API的使用方法不用赘述,但是在稍微复杂一点的业务中如何实现还是需要一些前期准备的。遇到的一些问题1.localStorage和sessionStorage适用于哪些业务场景?2.如何维护本地存储?3、如何进行版本控制?4、本地缓存被禁止时如何解决?一般情况下,localStorage根据自身特点用于长期存储,sessionStorage用于临时存储。暂时不讨论。很多初级前后端分离项目的习惯性误区是将用户token保存到localStorage中。这时候我遇到了一个问题:不同域名下需要共享登录信息怎么办?一种常见的做法是SSO。同域名下的小项目使用cookies的域做简单的跨域共享也是一种方式。这时候localStorage和sessionStorage就有了业务盲区。不仅难以通过,甚至通过各种鬼操作,擦屁股也会很麻烦:登录后如何将用户信息传递给其他域名?退出后如何删除所有页面的登录状态?当然,如果需要实现,还是要看后端对用户登录状态的判断,而这时候一些分离的太干净的业务可能会有一些奇怪的状态判断,比如a.xxx.comstationlogoutb.xxx.comstationsignup,如果真的需要前端来做这个,代码量是相当可观的,甚至每个页面缓存的token数据都可能不一样,这显然不合理也不行适合这样用请把后端还给后端,除非前端也写了一些node中间层。而且有些浏览器的incognito功能禁用了localStorage和sessionStorage,导致登录状态不正常,所以别把用户token存到localStorage里了,还是等会儿哭吧。那么要保存什么呢?保存不经常更改的内容?比如一张图片,把图片转成base64保存?那么问题来了,我们通常保存什么样的图片呢?喜欢一些背景图片吗?所以对于这件事情,我们第一次加载的时候,一定要先下载图片,然后全力保存,避免和其他同事重名。万一哪天我们需要换图,就得想办法把之前的内容清理干净。否则直接读取localStorage中的内容。即使本地存储的版本控制做好了,增删改查还是需要写很多代码。费那么大的力气,何必呢?所以保存文件这件事基本可以忽略不计。还有一些神奇的方法可以保存js代码。敢这样做的人,不是傻就是坏。然后,一般localStorage常用于缓存一些固定内容很多的数据,比如全国的省市县区号等基本不会变化但会用在各个ui组件中的简单数据,但是直接JSON.parse然后通过大量的数据进行查询和筛选,只会让你的机器感到绝望,红红火火,濒临崩溃。这个时候我还不如用cdn直接加载一个专门用来存放这种静态数据的js文件。快捷方便,性能好,可随时更换。localStorage真的这么没用吗?事实上,它不是。首先,我们必须确保不要保存太大的JSON数据,而应该保存一个小数据:用户搜索历史的缓存。在文本编辑器中输入的内容。然后是会话存储。其实我最喜欢用这个。关掉它并清除它,不用担心。我一般用在哪些业务场景:保存网页的历史记录,操作过histroyAPI的朋友一定知道,为了避免安全问题histroy只会给你当前页面之前的打开页数。所以你可以在这里详细记录一下历史,甚至可以结合spa项目的router插件来满足各种奇葩需求,比如跳几页填一堆表,点击支付,支付完成后点击浏览器上方的返回按钮也可以直接返回首页。或者保存那一堆临时表格的内容(2B业务经常遇到那种填写一大堆又臭又长的申请表,需要经过各种审批的功能)保存用户昵称等用户个人信息,不用每次都用每次刷新,再去服务器拖一遍(当然,这种东西其实也有一定的风险,万一用户在别处改了昵称,就得想办法同步了。)具体解决方法后面会介绍)如何保存?很多人的第一反应可能是直接使用localStorage.setItem这样的API。一旦你真的只做这件事……我可能不敢保证你不会被同事打。每个业务线本身都应该有一个状态管理区域。将这些业务线的本地数据存储服务聚合成一个共同的入口,进行类型判断和增删改查。一般对于Vue这样的应用,我们会将数据存储在Vuex的状态中,业务线的每个分支都会有单独的模块引入,独立维护。命名您必须确定具有一致、唯一名称的命名约定。这只是一个自娱自乐的项目。如果是4人以上的前端团队,每年可能会有不同的人离开。没有一个明确的标准,后果不堪设想。一般常见的命名方式会在前面带上USER_INFORMATION_NICKNAME等业务模块的名称。当然,有些信息可能不方便公开,只写一个索引名称。主要看公司里决定这条规则的人是怎么想的。增删改查依然以Vuex为例(以下内容仅供参考,请勿在业务代码中直接使用)在State中声明对象,获取本地存储内容的元数据状态:{NICKNAME:window.localStorage.getItem('USER_INFORMATION_NICKNAME')}为内容读取getter创建一个Getter:{USER_INFORMATION_NICKNAME:state=>{try{returnJSON.parse(state.NICKNAME)}catch(e){localStorage.removeItem('USER_INFORMATION_NICKNAME')returnnull}}}写入Mutation用于修改mutations:{DELETE_USER_INFORMATION_NICKNAME(state){window.localStorage.removeItem('USER_INFORMATION_NICKNAME')state.USER_INFORMATION_NICKNAME=value},UPDATE_USER_INFORMATION_NICKNAME(state,value){window.localStorage.setItem('USER_INFORMATION_NICKNAME',value)state.USER_INFORMATION_NICKNAME=null}}WriteAction信息同步操作:{GET_USER_INFORMATION_NICKNAME:context=>{$http.get('xxx').then(res=>{context.commit('UPDATE_INFORMATION_NICKNAME',res)}).catch(e=>xxx...)}}最基本的阅读策略已经完成。但是问题来了怎么删除呢?什么时候删除?毕竟是永久缓存,版本控制很重要,不然就是给自己挖坑。首先,删除数据的具体场景可能是短时间后失效的内容,可能是下一个大版本迭代的内容。发起部分用户想升级,部分用户维持现状,甚至可能因为新版本业务不完善而需要回滚灰度更新。一般情况下,我们需要在getter中确定一个读取数据的依赖。读取的内容可以跟随依赖数据,也可以不跟随依赖数据。这取决于具体的业务需求。如果你不遵循依赖或者它是一个依赖项目,你需要确定一些事情。版本过期时间可能是内容取决于父项版本0.0.1的内容。超过或低于这个版本都可能出现问题。需要及时删除,重新获取。可能是当前加载的页面中配置项的版本与自身版本不一致,需要去除数据并更新。因此,我们需要声明一个不保存在本地的配置JSON{"USER_INFORMATION":{"NICKNAME":"1.1.1","AGE":"1.1.2"...}}如果灰度更新是要执行,需要将此配置写入接口。另一种情况是设置一个过期时间,超过这个时间就会清除数据。所以我们需要在UPDATE方法中多写一些东西UPDATE_USER_INFORMATION_NICKNAME(state,value){constnew_value={expires:Date.now()+24*1000*30*3600,version:state.config.USER_INFORMATION.NICKNAME,value:value}window.localStorage.setItem('USER_INFORMATION_NICKNAME',JSON.stringify(new_value))state.USER_INFORMATION_NICKNAME=new_value}然后调整读取的逻辑,其他代码也相应调整,根据自己的能力封装即可横向封装,复用复用。至此初步完成了一个具有版本控制和过期控制的本地内容存储功能模块。做完这一切,感觉就像是,直到用户突然开启隐身模式……后面的问题只是把判断逻辑封装在业务里……所以,只需要有一个健壮的前端——端数据流是核心,其他只是辅助功能,帮助页面实现更好的体验。再好的东西,也不能滥用。最后基于对这件事的考虑,顺便写了一个本地存储控制库,API基本就在上面了。GITHUB:可控存储