LocalStorage 擴容

瀏覽器提供的localStorage本地存儲的最大空間是5M,如果不夠用呢,這時候就需要考慮來給localStorage擴容。

思路如下:

  1. 在【A域】下引入【B域】,【A域】空間足夠時,讀寫由【A域】來完成,數據存在【A域】下;
  2. 【A域】空間不夠需要在【B域】讀寫時,通過postMessage 向【B域】發送跨域消息,【B域】監聽跨域消息,在接到指定的消息時進行讀寫操作
  3. 【B域】接到跨域消息時,如果是寫入刪除可以不做什麼,如果是讀取,就要先讀取本域本地數據通過postMessage向父頁面發送消息
  4. 【A域】在讀取【B域】數據時就需要監聽來自【B域】的跨域消息

注意事項:

  1. window.postMessage()方法,向【B域】發消息,應用window.frames[0].postMessage() 這樣iframe內的【B域】纔可以接到
  2. 同理,【B域】向 【A域】發消息時應用,window.parent.postMessage()
  3. 【A域】的邏輯一定要在iframe 加載完成後進行
// index.html
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
    <title></title>
    </head>
    <body>
        <button class="set">存儲</button>
        <button class="get">讀取</button>
        <button class="remove">刪除</button>
        <iframe src="http://localhost:8000/storage.html"></iframe>   //嵌入【B域】的一個空頁面
    </body>
    <script src="js/localStorage.js"></script>
</html>
// storage.html
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title></title>
</head>
<body>
 
</body>
<script type="text/javascript">
    var fn = function(){};
    fn.prototype = {
        setLocal:function(key,value){
            localStorage.setItem(key,value);
        },
        getLocal:function(key){
            return localStorage.getItem(key);
        },
        removeLocal:function(key){
            localStorage.removeItem(key);
        },
        bindEvent:function(){
            var self = this;
            //監聽
            window.addEventListener('message',function(e){
                if(window.parent!=e.source) return;
                var option = JSON.parse(e.data);
                if(option.type.toLowerCase()=="get"){
                    var data = self.getLocal(option.key);
                    window.parent.postMessage(data,'*');
                }
                option.type.toLowerCase()=="set"&&self.setLocal(option.key,option.value);
                option.type.toLowerCase()=="remove"&&self.removeLocal(option.key);
            })
        },
        init:function(){
            var self = this;
            self.bindEvent();
        }
    }
    var tools = new fn();
    tools.init();
</script>
// 附件 localStorage.js
/*這段代碼是用來測試localStorage中字符串的編碼格式*/
/**
* 計算字符串所佔的內存字節數,默認使用UTF-8的編碼方式計算,也可制定爲UTF-16
* UTF-8 是一種可變長度的 Unicode 編碼格式,使用一至四個字節爲每個字符編碼
* 
* 000000 - 00007F(128個代碼)      0zzzzzzz(00-7F)                             一個字節
* 000080 - 0007FF(1920個代碼)     110yyyyy(C0-DF) 10zzzzzz(80-BF)             兩個字節
* 000800 - 00D7FF 
00E000 - 00FFFF(61440個代碼)    1110xxxx(E0-EF) 10yyyyyy 10zzzzzz           三個字節
* 010000 - 10FFFF(1048576個代碼)  11110www(F0-F7) 10xxxxxx 10yyyyyy 10zzzzzz  四個字節
* 
* 注: Unicode在範圍 D800-DFFF 中不存在任何字符
* 
* UTF-16 大部分使用兩個字節編碼,編碼超出 65535 的使用四個字節
* 000000 - 00FFFF  兩個字節
* 010000 - 10FFFF  四個字節
* 
* @param  {String} str 
* @param  {String} charset utf-8, utf-16
* @return {Number}
*/

function sizeof(str,charset){
    var strCode=0,charCode;
    charset = charset?charset.toLowerCase():'';
    if(charset=='utf-16'||charset=='utf16'){
        for(var i=0,len=str.length;i<len;i++){
            charCode = str.charCodeAt(i);
            strCode += charCode<0xffff?2:4;
        }
    }else{
        for(var i=0,len=str.length;i<len;i++){
            charCode = str.charCodeAt(i);
            strCode += (charCode<0x007f&&1)||(charCode<0x07ff&&2)||(charCode<0xffff&&3)||4;
        }
    }
    return strCode/1024/1024/2;
}
/*測試localStorage中字符串的編碼格式結束*/
function storage(type,key,value){
    var val = localStorage.getItem(key);
    switch (type){
        case 'get':
            if(val){
                return val;
            }else{
                return window.frames[0].postMessage(JSON.stringify({type:type,key:key}),'http://localhost:8000');
            }
            break;
        case 'set':
            if(!val&&sizeofLocal()+sizeof(value)>5){
                            window.frames[0].postMessage(JSON.stringify({type:type,key:key,value:value}),'http://localhost:8000');
            }else{
                localStorage.setItem(key,value);
            }
        break;
        case 'remove':
            if(val){
                localStorage.removeItem(key);
            }else{ window.frames[0].postMessage(JSON.stringify({type:type,key:key}),'http://localhost:8000');   
            }
            break;
        default:
            break;
    }
}
function sizeofLocal(){
    var myStr = '',charCode,strCode=0;
    for(item in localStorage){
        if(localStorage.hasOwnProperty(item)){
            myStr += localStorage.getItem(item);
        }
    }
    for(var i=0,len=myStr.length;i<len;i++){
        charCode = myStr.charCodeAt(i);
        strCode += charCode<0xffff?2:4;
    }
    return strCode/1024/1024/2;
}
var myStr='';
for(var i=0;i<1024*1200;i++){
    myStr += 1+'12'+'啦';
}
document.querySelector(".set").onclick = function(){
    storage("set","yoyo",myStr);
}
document.querySelector(".get").onclick = function(){
    storage("get","yoyo");
    window.addEventListener('message',function(e){
        window.myStorage = e.data;  
    })
}
document.querySelector(".remove").onclick = function(){
    storage("remove","yoyo");
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章