• Safari无痕模式下,storage被禁用问题


    前言

    Safari开启无痕模式后,localStorage和sessionStorage为空,对其进行set操作也会报错,也就是说这种情况下,storage是被禁止使用了。接下来说一下解决方法。

    解决方案

    我们项目框架上的解决方法是对storage进行一层封装,遇到这种开启无痕模式的情况,会定义一个window的全局变量,把之前准备存放到storage的内容改为存到这个全局变量中。

    注意,无痕模式下localStorage和sessionStorage对象本身依然是存在的,只是调用setItem方法是会报错。下面是无痕模式下报错的截图:

    所以正确的判断代码应该是这样:

      try {
          sessionStorage.setItem('private_test', 1);
        } catch (e) {
          //无痕模式
        }
    

    我们会另外定义一个NameStorage对象,在原生storage失效时使用:

     // 隐私模式下面,把临时值存到window.name中去
      function NameStorage(type) {
        this.store = NameStorage[type];
      }
    
    
      Object.assign(NameStorage.prototype, {
        getItem: function(key) {
          return this.store[key];
        },
        setItem: function(key, value) {
          this.store[key] = value;
          this._saveNameValue();
        },
        removeItem: function(key) {
          delete this.store[key];
          this._saveNameValue();
        },
        clear: function() {
          this.store = {};
          this._saveNameValue();
        },
        _saveNameValue: function() {
          var ret = {
            session: NameStorage.session,
            local: NameStorage.local
          }
    
          window.name = JSON.stringify(ret);
        }
      });
    

    上面会把所有的local和session数据存储到window.name上去,然后在每个页面启动时,调用一下keepName方法,把window.name的数据拿下来放到NameStorage上面。这时候,只需要调用new NameStorage('local')来代替localStorage进行操作就行了

     function keepName () {
        if (keepName.done) {
          return;
        }
    
        var ret;
    
        if (window.name) {
          try {
            ret = JSON.parse(window.name);
          } catch (e) {
            ret = {};
          }
        }
    
        if (!_.isPlainObject(ret)) {
          ret = {};
        }
    
    
        if (!ret.session) {
          ret.session = {};
        }
    
        if (!ret.local) {
          ret.local = {};
        }
    
    
        NameStorage.session = ret.session;
        NameStorage.local = ret.local;
        keepName.done = true;
      }
    

    另外一些补充

    ● 无痕模式下,localStorage和sessionStorage的报错信息是:QuotaExceededError,code为22,这个其实是storage存储空间用完了报的错,就比如当前浏览器storage内存为5mb,你已经存储了5mb的数据后,再进行setItem操作就会报这个错误。

    ● 所以我猜想无痕模式下,浏览器是把storage的内存先清空,然后再设置最大值为0,这样调用setItem就直接报错了。

    ● 另外无痕模式下cookie是可以使用的,大概因为cookie是跟服务器有关,而storage是属于浏览器的特性吧。

    ● 最后还有一种情况,就是无痕模式下打开了某个页面,然后把浏览器关闭再打开,这个时候会打开访问的页面,但是window.name已经丢失了,所以就拿不到以前存储的数据了。这种情况只能页面做容错处理了。

  • 相关阅读:
    SCOM 初探 [SCOM应用系列之一]
    SCOM 安装部署 [SCOM应用系列之二]
    CMMI 配置管理(Configuration Management)系列(1) 简介
    设计模式总结之创建型设计模式
    tabbar图片渲染的问题
    react实现自定义hooks(节流和防抖)
    前端工程化5js源码编译和ast
    react实现自定义hooks(跑马灯)
    react实现自定义hooks(倒计时)
    react实现自定义hooks(移动端拖拽)
  • 原文地址:https://www.cnblogs.com/both-eyes/p/10106121.html
Copyright © 2020-2023  润新知