多页面共享Storage

190 阅读1分钟

需求:项目要实现一个项目登录后,同域名下另一个项目页面也自动登录,不需要重新登录。

开始不知道要做相同域名下的数据共享,于是就按不同域名前提的数据进行研究,首先用到的是postMessage,但是经过研究发现,postMessage只有在两种情况下才可以实现页面数据共享:第一种是父页面同iframe页面之间,第二种是通过在父页面中使用window.open(url)方法打开子页面,通过window.open(url)能够拿到子页面的window对象,子页面也可以通过window.opener拿得到父页面的window对象以此实现数据共享,但是限制是只有通过父页面打开子页面才能实现两页面间的数据沟通。不符合需求。

后来了解到两个项目部署在同一域名下,于是采用了借助localStorage实现sessionStorage的方法,其实localStorage可以直接实现,但是考虑到localStorage生命周期过长,只有用户主动清除才会消失,比较不安全,需要在当前浏览器关闭之后自动清除的功能(类似sessionStorage)。代码如下:

//utiles/memoryStorage.ts
const MemoryStorage =  class {
    constructor(){
        this.data = {};
    }
    setItem(k, v){
        this.data[k] = v;
        MemoryStorage.dataSendHandler( this.data );
    }
    getItem(k){
        return this.data[k];
    }
    removeItem(k){
        delete this.data[k];
        MemoryStorage.dataSendHandler( this.data );
    }
    clear(){
        this.data = {};
        MemoryStorage.dataSendHandler( this.data );
    }
    static dataSendHandler( data ){
        localStorage.setItem('setMemoryStorage', JSON.stringify(data));
        localStorage.removeItem('setMemoryStorage');
    }
    static dataGetHandler(){
        localStorage.setItem('getMemoryStorage', new Date().getTime());
        localStorage.removeItem('getMemoryStorage');
    }
}
const initMemoryStorage = function(){
    var memoryStorage = new MemoryStorage();
    window.addEventListener('storage',function(e){
        if( e.newValue===null ) return false;
        if(e.key == 'getMemoryStorage'){
            console.log('有其他页面取memory')
            MemoryStorage.dataSendHandler( memoryStorage.data );
        }
        else if(e.key == 'setMemoryStorage'){
            let data = JSON.parse(e.newValue);
            if( isEmptyObj(data) ){
                console.log('memory被清空了')
                memoryStorage.data = {};
            }else{
                console.log('memory被修改了')
                for(let k in data){
                    memoryStorage.data[k] = data[k];
                }
            }
        }
    })
    if( isEmptyObj(memoryStorage.data) ){
        MemoryStorage.dataGetHandler();
    }
return memoryStorage;
}
function isEmptyObj(obj){
    for(let i in obj){
        return false;
    }
    return true;
}
export default initMemoryStorage;

//main.ts
import memory from "@/utiles/memoryStorage.ts"

window.memoryStorage = memory()

这样可以实现同域名下多标签页sessionStorage共享的需求。