这样讲 webStorage,面试官会对你另眼相看

图片:Unsplash
做者:Erda Estremera

localStorage 只在相同的域下共享同一空间。协议和端口都有影响,注意:javascript

  • http://a.comhttps://a.com不共享
  • http://a.com:80http://a.com:8080 不共享
  • http://a.comhttp://a.com:80 共享

✔ 经常使用 API

设置 localStorage

Chrome 面板查看

  • localstorage.setItem(key, value) 存数据,key value 都会被转换成字符串,为了防止意料以外的状况,最好先将其转化为字符串了再存储;
  • localstorage.getItem(key) 获取数据,key 都会被转换成字符串;
  • localstorage.clear() 清除当前域下 localStorage 存储的数据;
  • localstorage.length 获取当前域下存储的项目条数;
  • localstorage.key(n:number) 获取显示面板中第 n 条的 key,感受比较鸡肋;

✔ 浏览器对 localStorage 容量限制

经测试,Chrome、FireFox、Edge 都是 5M(IE 忽略)。html

下面是容量探测代码,能够精确到 1K。前端

const add10KStr = new Array(1024).fill('0000000000').join('') // 10240 Byte => 10K
const add1KStr = new Array(1024).fill('1').join('') // 1024 Byte => 1K
const storageKey = 'QuotaTest'

function localStorageQuota() {
  localStorage.clear()
  function setText(str) {
    console.log(str)
  }
  let total = ''
  let interval = null
  interval = setInterval(() => {
    try {
      setText(`数据插入中 => ${total.length / 1024}K`)
      localStorage.removeItem(storageKey)
      localStorage.setItem(storageKey, total + add1KStr)
      total += add10KStr
    } catch (e) {
      clearInterval(interval)
      if (e && e.code === 22) {
        setText('超过容量(10K增长)')
        setText(`当前存储了${total.length / 1024}K`)
        interval = setInterval(() => {
          try {
            setText(`数据插入中 => ${total.length / 1024}K`)

            localStorage.removeItem(storageKey)
            localStorage.setItem(storageKey, total + add1KStr)
            total += add1KStr
          } catch (ee) {
            clearInterval(interval)
            if (ee && ee.code === 22) {
              setText('超过容量(1K增长)')
              setText(`当前存储了${total.length / 1024}K`)
            }
          }
        }, 0)
      }
    }
  }, 0)
}
复制代码

以 Chrome 为 例,插入不了的时候会抛出异常,e.code 是 22。java

localStorage error

✔ Storage Event

Storage 事件能够用来在同域下的页面之间实现广播机制,该事件是在 window 上触发的。该事件不在致使数据变化的当前页面(tab)触发(若是浏览器同时打开一个域名下面的多个页面,当其中的一个页面改变 localStorage 的数据时,其余全部页面的 storage 事件会被触发,而原始页面并不触发 storage 事件);nginx

event 包含的关键信息:git

  • event.key 发生变动的 key
  • event.oldValue 变动以前的值;
  • event.newValue 变动以后的值;

触发的条件有两个:github

  1. 不在当前的 tab 触发,相同的 url 在两个不一样的 tab 也是会触发的;
  2. localstorage.setItem(key, value) 只有当后一次设置的 value 不一样的时候才会触发该事件,相同的话也没有必要触发了;

例如在 https://a.com/a.html 有以下代码:sql

localStorage.setItem('name', 'lx')
window.addEventListener('storage', e => {
  console.log('e', e)
})
复制代码

这个时候,在 https://a.com/b.html 进行了下面的操做:json

localStorage.setItem('name', 'lxfriday')
复制代码

则 a 页面会打印出下面的内容:浏览器

storage event

✔ localStorage 的其余用途

ref

  1. 缓存静态文件;
  2. 做为前端 DB 的存储介质;

✔ sessionStorage

它与 localStorage 类似,不一样之处在于 localStorage 里面存储的数据没有过时时间设置,而存储在 sessionStorage 里面的数据在页面会话结束时会被清除(关闭当前页面的时候会清除)

页面会话在浏览器打开期间一直保持,而且 从新加载(刷新) 或恢复页面仍会保持原来的页面会话。在新标签或窗口打开一个页面时会复制顶级浏览会话的上下文做为新会话的上下文,这句很差理解,意思是点击当前页面的 <a target="_black"></a> 标签时,在新页面中的 sessionStorage 的值是复制的当前页面的,注意并非共用的。

✔ sessionStorage 应用

  1. 存储用户输入的内容,当页面刷新的时候能够马上显示出刷新前的内容;
  2. 对使用 browser historay 部署的单页应用,能够在前端使用 sessionStorage 实现路由匹配(不会报 404),不须要使用 nginx 作一次转发;

实现自动匹配路由的过程是这样的:当访问 a.com/page1 页面的时候,因为服务器并无这个页面,服务器会返回 404.html(浏览器当前的路由仍然是 a.com/page1),浏览器执行 404.html 时会先设置 sessionStorage.redirect 为当前的 url,而后 <meta> 会马上让页面跳转到 /,服务器此时会返回 index.html,浏览器执行 <script> 中的代码获取到 sessionStorage.redirect,而后执行 history.replaceState 替换当前的 url,这样就达到了想要的跳转效果(histpry.replaceState 只会更改浏览器地址栏,不会让浏览器主动去服务器获取对应的页面)。

设置一个 404.htmlhead 中包含下面内容

<head>
    ...
    <script> sessionStorage.redirect = location.href; </script>
    <meta http-equiv="refresh" content="0;URL='/'"></meta>
</head>
复制代码

在单页应用的模板 index.html 中,填下面的代码:

<body>
  <div id="root"></div>
  <script> // 这段代码要放在其余js的前面 ;(function() { var redirect = sessionStorage.redirect delete sessionStorage.redirect if (redirect && redirect != location.href) { history.replaceState(null, null, redirect) } })() </script>
</body>
复制代码

演示

sessionStorage 实现页面跳转


关注公众号,回复 加群 ,添加号主微信,将会拉你进交流群,有任何问题都会回复,欢迎加入。

感谢阅读,欢迎关注个人公众号 云影 sky,带你解读前端技术,掌握最本质的技能。

公众号
相关文章
相关标签/搜索