• 使用iframe给页面的localStorage扩容


    浏览器提供的localStorage本地存储的最大空间是5M,如果不够用呢,这时候就需要考虑来给localStorage扩容。

    思路如下:

    1. 在【A域】下引入【B域】,【A域】空间足够时,读写由【A域】来完成,数据存在【A域】下;当【A域】空间不够时,读写由【B域】来完成,数据存在【B域】下

    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 加载完成后进行

    【A域】的页面如下:

    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>
    

    由于需要判断【A域】的空间是否足够,所以需要计算【A域】已经被占用的空间。那么localStorage中的字符串以什么编码格式存储的呢?
    经过反复试验发现,当使用utf-16的编码方式进行计算时,当存储的字符串大于5M时,浏览区就会报错:字符串大小超过最大值。
    所以localStorage中的字符串是以utf-16进行编码的。

    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");
    }
    

    【B域】的页面如下

    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>
    
  • 相关阅读:
    Git使用方法
    设计模式之原型模式
    php基础查找算法
    php基础排序算法
    设计模式之工厂模式
    设计模式之代理模式
    设计模式之装饰者模式
    设计模式之六大原则
    设计模式之策略模式
    设计模式之简单工厂模式
  • 原文地址:https://www.cnblogs.com/cherishSmile/p/8390754.html
Copyright © 2020-2023  润新知