关闭

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

时间: 2018-03-16阅读: 1823标签: 存储

前言

关于localStorage sessionStorage之类的api怎么用已经无需我再赘述了,但是具体怎么落实到一个稍微复杂一些的业务中还是需要做一些前期的准备


遇见的一些问题

1.localStorage 与 sessionStorage具体适用于什么样的业务场景?
2.如何维护本地储存?
3.如何进行版本控制?
4.碰到禁止本地缓存的情况下怎么解决这个问题?


常见情况

根据本身特性localStorage做长期存储, sessionStorage做临时存储大家都是清楚的也无需赘述,至于IndexedDB之类的暂时不做讨论。
很多初级的前后端分离的项目习惯性误区是把用户token存到localStorage。
这时候碰到一个问题:

如果需要在不同域名下做登陆信息共享该怎么办?

常见做法是SSO,同一个域名下的小型项目用cookies的domain直接来做简单的跨域共享也是一个办法,而这个时候localStorage和sessionStorage就出现业务盲点了。
不仅过不去,即使通过各种鬼畜的操作过去了后面擦屁股也麻烦的要死:

  1. 登陆了以后用户信息怎么传给别的域名?
  2. 退登的话怎么删除所有页面的登陆状态?

当然如果需要实现还是比较依赖后端的用户登陆状态判定,而这个时候某些分离得过分干净的业务可能出现一些诡异的状态判定,比如a.xxx.com站退登了b.xxx.com站还登着,你要真要前端来做这事代码量也是相当可观的,甚至各个页面缓存的token数据可能还都不一样,显然不够合理也不适合这样用,请把后端的事情还给后端,除非前端也写一些node中间层。
而且某些浏览器的无痕功能禁用了localStorage和sessionStorage导致登陆状态异常,所以localStorage存用户token的事情就把它忘记吧,不然后面就等着哭吧。


那么存什么好呢?

存些不常变的东西?
比如图片,把图片转成base64再存起来?
那么问题来了,一般我们会存什么图片?
比如一些背景图?
那么为了这件事情我们首次载入的时候先要把图片下载过来,然后费尽心思存起来还要避免和别的同事重名,万一哪天要换个图片还要想办法把之前的内容清理掉不然直接读localStorage里的内容,即使做好了本地存储的版本控制还要专门写一大堆代码增删改查,这明显是嫌自己工作量不够大,本来只要用cdn直接解决的东西被搞得这么费劲,何必呢?
所以存文件的事情基本也可以忽略了。

还有一些神奇的做法是存js代码,敢这样做的人不是蠢就是坏了。

然后,一般localStorage常用于缓存一些内容很多很固定的数据比如全国各地省市县、区号之类的基本不会变但又会在各种ui组件里用到的简单数据,但是直接jsON.parse然后还去遍历一个很大的数据做查询筛选只会让你的机器感到绝望发红发烫濒临崩溃,而这个时候我还不如直接用cdn载入一个专门用于存放这类静态数据的js文件来得快捷方便性能还好还能随时改。

难道localStorage真的这么废?

其实也不是啦,首先要确定一点,不去存过大的JSON数据,那就存个小的:

  1. 用户搜索历史的缓存。
  2. 文本编辑器内输入的内容。

然后是sessionStorage,其实我最喜欢用这个了,关掉就清除毫无后顾之忧,那一般我会用于什么业务场景呢:

  1. 存网页的历史记录,操作过histroyAPI的朋友一定知道为了避免安全性问题histroy只会给你当前页面前面打开过几个页面的数量。所以完全可以在这里做个histroy的详细记录,甚至结合spa项目的router插件来满足各类奇怪的需求,比如跳了好几次页面填了一堆表格后点击支付然后支付完成后即使点击浏览器顶部的后退按钮也能直接一脚跨回首页。
  2. 或者存那堆临时表格的内容(2B业务经常碰到那种填一大堆又臭又长的申请表还要经过各种审批的功能)
  3. 存用户个人信息,比如用户昵称之类的,不用每次刷新都去服务器拖一遍(当然这种事情其实还是有一定风险的,万一用户在别的地方改昵称了,你还得想办法同步,具体解决办法后面说)


怎么存?

很多人第一反应可能是直接使用 localStorage.setItem之类的api
一旦你真的只这样做了...我可能无法保证你不被同事揍


入口

每个业务线本身应该有个状态的管理区域,而这些业务线的本地数据存储业务应该汇总入到一个公共的入口做类型判定以及进行增删改查。
一般比如vue的应用,我们会把数据存到vuex的state内,每个业务线分支都会有单独的模块引入并进行独立维护。


命名

你必须确定一个习惯一致,名字唯一的命名协议。
自娱自乐的项目也就罢了,万一是个超过四个人的前端小队每年可能都有不同的人会离职不同的人会入职不同的业务要迭代不同的功能要修改,增删改查的事情如果没有一个确定的标准后果不堪设想。
一般常见命名方式会在前面带入业务模块名称
比如 USER_INFORMATION_NICKNAME 之类的,当然有的信息可能不方便透露只写个索引名称也是有的,主要还是看公司里决定这个规则的人怎么考虑。


增删改查

还是以Vuex做为例子(以下内容仅供参考,请勿直接用于业务代码中)

在State中声明对象用于获取本地存储内容的元数据

state:{
  NICKNAME: window.localStorage.getItem('USER_INFORMATION_NICKNAME')
}

创建一个Getter用于内容读取

getters: {
  USER_INFORMATION_NICKNAME: state => {
    try {
      return JSON.parse(state.NICKNAME)
    } catch (e) {
      localStorage.removeItem('USER_INFORMATION_NICKNAME')
      return  null
    }
 }
}

写入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
  }
}

写入Action用于信息同步

actions: {
  GET_USER_INFORMATION_NICKNAME:context => {
    $http
    .get('xxx')
    .then(res=> {
      context.commit('UPDATE_INFORMATION_NICKNAME', res)
    })
    .catch(e => xxx...)
 }
}

这样一个最最最基本的读取策略已经完成了。
但问题又来了


怎么删?什么时候删?

毕竟是永久缓存,版本控制非常重要,不然就是给自己挖坑
首先要明确删除数据的具体场景

  1. 可能是只存一小段时间后就失效的内容
  2. 可能是下个大版本会被迭代掉的内容
  3. 可能会发起部分用户要升级部分用户维持现状甚至因为新版本业务不够完善可能需要回滚的灰度更新。

一般情况下我们需要在getter内先确定一个数据读取的依赖项,读取的内容可能是跟着依赖项数据走也可能不跟着依赖项数据走,这个看具体业务需求,如果不跟着依赖项走或者本身就是被依赖的项目的话就需要确定几件事情

  1. 版本
  2. 过期时间

可能该内容依赖于父级项 0.0.1版本的内容,超过或者低于这个版本都可能出现问题需要及时删除并重新获取
可能当前载入的页面中的配置项的版本与自身版本不一致所以需要移除并更新数据
于是导致的结果是我们需要再去声明一个不保存在本地的配置JSON

{
  "USER_INFORMATION": {
    "NICKNAME": "1.1.1",
    "AGE": "1.1.2"
    ...
  }
}

如果要进行灰度更新的话,这个配置就需要写入到接口里面了。
还有个情况就是设置过期时间,超出这个限定的时间就清空数据。
于是我们就需要在UPDATE方法内多写入些东西

UPDATE_USER_INFORMATION_NICKNAME (state, value) {

  const new_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
}

再调整下读取的逻辑,
其他的代码也跟着做一遍调整,依照自己能力水平能封装的封装,能复用的复用。
于是一个拥有版本控制和过期控制的本地内容存储功能模块就算初步完成了。
做完这一切虽然感觉好像是像那么回事了


直到用户突然开启了无痕模式....

后面的问题也只是封装业务中的判断逻辑罢了...
所以,有一个健壮的前端数据流才是核心,其他的只不过是帮助页面达到更好的体验的辅助功能罢了,东西再好也不能滥用。


转载来源:https://segmentfault.com/a/1190000013768365
作者:MaxChan
站长推荐

1.云服务推荐: 国内主流云服务商,各类云产品的最新活动,优惠券领取。地址:阿里云腾讯云华为云

2.广告联盟: 整理了目前主流的广告联盟平台,如果你有流量,可以作为参考选择适合你的平台点击进入

链接: http://www.fly63.com/article/detial/510

关闭

Token ,Cookie和Session的区别

在做接口测试时,经常会碰到请求参数为token的类型,但是可能大部分测试人员对token,cookie,session的区别还是一知半解

localStorage本地持久化存储API

localStorage, 是一个用来做本地持久化存储的Web Api。 localStorage以键值对的形式存储数据。用法很简单:localStorage是以『源(origin)』为维度进行存储的。

前端 cookie与本地存储与实践

一个项目考虑缓存和不考虑缓存完全是两个难度,在用户体验上也截然不同。考虑缓存肯定得了解web本地存储与它们的区别和适用场景。正好这次负责一个项目,在做了这个项目后抽空给大家来一次总结,希望能给大家带来帮助。

SessionStorage、LocalStorage详解

作为Web开发人员,在 Web浏览器中存储数据以改善用户体验和提升Web应用程序性能是非常常见的。在大多数情况下,可供我们使用就是LocalStorage和SessionStorage。

前端数据保存_使用js开发数据库

前端很多时候还是需要保存一些数据的,这里的保存指的是长久的保存。以前的思想是把数据保存在cookie中,或者将key保存在cookie中,将其他数据保存在服务器上。想要一种能够长久的保存在本地的数据,类似数据库或者类似web sql。

Web 存储技术

第一个Web存储的技术叫做Cookie,它是网站的身份证。是网站为了辨别用户身份,进行session(服务端的session)跟踪而存储在用户本地终端上的数据,也就是说它是存在电脑硬盘上的,一个很小的txt类型的文件

Cookie、Session与Token

Cookie是一个http请求首部,当服务端响应头上标记着setCookie时,可以设置此cookie到当前域名下;session实际上是一种概念,表示每次会话服务器存储的用户信息

Cookie防篡改机制_cookie怎么防止被篡改/伪造

因为Cookie是存储在客户端,用户可以随意修改。所以存在一定的安全隐患,服务器为每个Cookie项生成签名。如果用户篡改Cookie,则与签名无法对应上。以此,来判断数据是否被篡改。

Oss 对象服务存储前端方法封装

根据oss url 获取文件数据流,文件单个/多个下载,常用的文件类型,文件大小转换

H5的sessionStorage和localStorage

H5 新增的 sessionStorage 和 localStorage 的区别:sessionStorage 和 java 的 session 差不多,可以短时间存储信息,电脑浏览器常用sessionStorage 存储用户登录信息,localStorage 可以永久保留用户信息,不用每次都登录,常用于APP

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!