关于javascript:解决sessionStorage不能跨标签页共享

用户在一个标签页已登录,再关上多个标签页,此场景下将token保留在sessionStorage中将会带来很差的用户体验,每次开启一个标签页都会要求用户从新登录。

sessionStorage顾名思义是针对一个session的数据存储,生命周期为以后窗口,一旦窗口敞开,那么存储的数据将被清空。最初还有一个很次要的区别同一浏览器的雷同域名和端口的不同页面间能够共享雷同的 localStorage,然而不同页面间无奈共享sessionStorage的信息。

解决:
在index.html中减少以下代码,复制全副sessionStorage内材料

(function(){
    // 判断以后页面是否存在sessionStorage
    if (!sessionStorage.length) {
        // 这个调用能触发指标事件,从而达到共享数据的目标(若不存在则加上一个localStorage Item,key=getSessionStorageData)
        localStorage.setItem('getSessionStorageData', Date.now());
    };

    // 该事件是外围,减少window监听事件 
    window.addEventListener('storage', function(event) {
         // 已存在的标签页会收到这个事件,如果监听到的事件key是getSessionStorageData
         if (event.key == 'getSessionStorageData') {
             // 再新增一个localStorage Item,key=sessionStorageData,value就是以后的sessionStorage
            localStorage.setItem('sessionStorage', JSON.stringify(window.sessionStorage));
            // 删除localStorage中key=sessionStorageData的item
            localStorage.removeItem('sessionStorage');

        } 
        if (event.key == 'sessionStorageData' && !sessionStorage.length) {
            // 新开启的标签页会收到这个事件,把sessionStorageData的材料parse进去
            const data = JSON.parse(event.newValue);
            //  赋值到以后页面的sessionStorage中
            for (key in data) {
                window.sessionStorage.setItem(key, data[key]);
            }
        }
    });
})();

整体流程:
1、判断页面是否存在sessionStorage,并加上store事件的监听;
2、若不存在,就把本来的sessionStorage内的材料复制到localStorage中并取名为sessionStorageData;
3、若storage事件监听到key为sessionStorageData的事件,就把内容通过for赋值到页面sessionStorage中;

为什么复制到localStorage后又间接删除?
因为window增加了监听事件

window.addEventListener('storage', ..)

这就意味着每次storage事件被触发的时候都会执行,所以当setItem(‘sessionStorage’)的时候,也会接管到事件,
代表着

window.localStorage.removeItem('sessionStorage')

其实是产生在sessionStorage被写入之后的事件了,所以能够同时写入和删除,不留下localSorage的记录。

新开的页面为什么会有sessionStorage能够提供复制?
查问API(Using the Web Storage API|MDN)后晓得,各标签只有是同域名,有对storage动作时全副都会被连动,storage事件能够做到同域名的状态监测。

storage事件的测试
轻易开两个同域名的标签页后,别离开启开发者工具:
1、在A标签页下

window.addEventListener('storage', (event) => console.log(event));

2、在B标签页下

window.localStorage.setItem('storageTest', 'test');

3、再回头看A标签页,就会发现曾经被监听到storage事件了。
通过这样的事件监听,就能够达到由localSorage传递sessionStorage的目标。

对于登出
登出时同步革除所有标签页的sessionStorage并reload页面

(function(){
    // 判断以后页面是否存在sessionStorage
    if (!sessionStorage.length) {
        // 这个调用能触发指标事件,从而达到共享数据的目标(若不存在则加上一个localStorage Item,key=getSessionStorageData)
        localStorage.setItem('getSessionStorageData', Date.now());
    };

    // 该事件是外围,减少window监听事件 
    window.addEventListener('storage', function(event) {
         // 已存在的标签页会收到这个事件,如果监听到的事件key是getSessionStorageData
         if (event.key == 'getSessionStorageData') {
             // 再新增一个localStorage Item,key=sessionStorageData,value就是以后的sessionStorage
            localStorage.setItem('sessionStorage', JSON.stringify(window.sessionStorage));
            // 删除localStorage中key=sessionStorageData的item
            localStorage.removeItem('sessionStorage');

        } 
        if (event.key == 'sessionStorageData' && !sessionStorage.length) {
            // 新开启的标签页会收到这个事件,把sessionStorageData的材料parse进去
            const data = JSON.parse(event.newValue);
            //  赋值到以后页面的sessionStorage中
            for (key in data) {
                window.sessionStorage.setItem(key, data[key]);
            }
        }
        // ===== 加上面这段 =====
        if (event.key === 'logout') {
            // 接管到logout事件,进行sessionStorage的革除和页面reload
            window.sessionStorage.clear();
            window.location.clear();
        }
    });
})();

其余
即便这样看起来ok,但还是有缺点
1、Chrome,FireFox的复原分页性能会将sessionStorage的材料一起复原,这可能会导致一些安全性问题(不过相较于localStorage,这应该不算问题)
2、这些数据是标签页被开启的同时获取的,意味着如果你的sessionStorage贮存着常常被变动的材料,必须再写一些事件去拦挡和复制,因为storage事件不会监听到其余页面的sessionStorage变动.

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理