本文最后更新于:2024年11月13日 下午
                
              
            
            
              html5标准中一个亮点就是提供了浏览器本地存储的功能。方式有两种:localStorage和 sessionStorage。 相对于cookie,他们具有存储空间大的特点,一般可以存储5M左右,而cookie一般只有4k。
localStorage和 sessionStorage的主要区别是:localStorage的生命周期是永久的,意思就是如果不主动清除,存储的数据将一直被保存。而sessionStorage顾名思义是针对一个session的数据存储,生命周期为当前窗口,一旦窗口关闭,那么存储的数据将被清空。
当然作为孪生兄弟,两者也有很多相同点。比如存取数据的方法就是一样的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 #localStorage 和sessionStorage的一些方法:setItem (key,value);getItem (key);removeItem (key);clear ();key (index);localStorage  的存取方式localStorage .age  = 88 ; localStorage .setItem ("animal" ,"cat" ); var  animal = localStorage .getItem ("animal" ); console .log (animal);  localStorage .removeItem ("animal" ); localStorage .clear (); work  = "police" ;setItem ("person" , "Li Lei" );var  person = sessionStorage.getItem ("person" );console .log (person);
另外,不同浏览器无法共享localStorage和sessionStorage中的信息。同一浏览器的相同域名和端口的不同页面间可以共享相同的 localStorage,但是不同页面间无法共享sessionStorage的信息。这里需要注意的是,页面仅指顶级窗口,如果一个页面包含多个iframe且他们属于同源页面,那么他们之间是可以共享sessionStorage的。在实际开发过程中,遇到的最多的问题就是localStorage的同源策略问题。为了了解这个问题,我们先得清楚什么是同源策略。同源策略(same-origin policy )是浏览器执行的一种安全措施,目的是为了保证用户信息的安全,防止恶意的网站窃取数据。浏览器的同源策略具体如下:
只要不同源就不能共享localStorage的数据。但是在实际开发中又时常会遇到这样的需求,那我们该如何解决呢?
目前广泛采用的是postMessage和iframe相结合的方法。postMessage(data,origin)方法允许来自不同源的脚本采用异步方式进行通信,可以实现跨文本档、多窗口、跨域消息传递。接受两个参数:
data:要传递的数据,HTML5 规范中提到该参数可以是JavaScript 的任意基本类型或可复制的对象,然而并不是所有浏览器支持任意类型的参数,部分浏览器只能处理字符串参数,所以在传递参数时需要使用JSON.stringify()方法对对象参数序列化。 
origin:字符串参数,指明目标窗口的源,协议+主机+端口号[+URL],URL会被忽略,所以可以不写,只是为了安全考虑,postMessage()方法只会将message传递给指定窗口,当然也可以将参数设置为”*“,这样可以传递给任意窗口,如果要指定和当前窗口同源的话设置为”/“。 
 
具体示例:http://www.test.com/index_a.html 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 <!DOCTYPE html > <html  lang ="en" > <head > <meta  charset ="UTF-8" > <title > cross domain</title > </head > <body > <h2 > Status</h2 > <p > </p > <a  href ="http://www.test2.com/index_b.html" > 去index_b查看结果</a > <iframe  src ="http://www.test2.com/getmessage.html"  frameborder ="0" > </iframe > <script >         window .onload  = function (                          window .frames [0 ].postMessage ('jogging, reading and writing' ,'http://www.test2.com' );         }                  window .addEventListener ('message' , function (e ){             var  data = e.data ;             document .querySelector ('p' ).innerHTML  = data;         }, false );      </script > </body > </html > 
http://www.test2.com/getmessage.html 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <!DOCTYPE html > <html  lang ="en" > <head > <meta  charset ="UTF-8" > <title > getmessage</title > </head > <body > <script >                  window .addEventListener ('message' , function (e ) {               if  (e.source  != window .parent )                    return ;               console .log (e.data );             localStorage .setItem ('task' ,e.data );             window .parent .postMessage ('finished' , '*' );           }, false );      </script > </body > </html > 
http://www.test2.com/index_b.html 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 <!DOCTYPE html > <html  lang ="en" > <head > <meta  charset ="UTF-8" > <title > Document</title > </head > <body > <div > 点击获取任务</div > <p > </p > <script >         document .querySelector ('div' ).addEventListener ('click' , function (             document .querySelector ('p' ).innerHTML  = localStorage .getItem ('task' );         }, false );      </script > </body > </html > 
以上示例中,很好的实现了localStorage的跨域存储功能。这样就算解决问题了吗?
我们还会遇到另一个棘手的问题。在safari浏览器下,这种方法就不可行了。由于safari浏览器的默认限制,父页面无法向iframe里的跨域页面传递信息。这时针对safari浏览器就得另辟蹊径了。本人在项目中用的方法是在safari浏览器下,用url传值的方法来实现跨域存储功能。用这种方法有一个问题必须要先考虑的,就是safari浏览器的url能够支持多长的字符呢? url的长度极限是由两方面决定的,一个是浏览器本身的限制,另一个就是服务器的限制。有人在Apache 2.4服务器上设置了一个非常大的LimitRequestLine 和 LimitRequestFieldSize,然后进行测试,结果表明safari浏览器可以支持超过64k个字符的长度。一般服务器默认支持2~3万个字符长度的url不成问题。所以只要需要传输的数据量不是非常大的话,可以直接通过url来进行传递,如此就能解决safari下的跨域存储问题。示例如下:
http://www.test.com/index_a.html 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 <!DOCTYPE html > <html  lang ="en" > <head > <meta  charset ="UTF-8" > <title > cross domain</title > </head > <body > <h2 > Status</h2 > <p > </p > <a  href ="http://www.test2.com/index_b.html" > 去index_b查看结果</a > <iframe  src ="http://www.test2.com/getmessage.html"  frameborder ="0" > </iframe > <script >         var  isSafari = navigator.userAgent .indexOf ("Safari" ) > -1  && navigator.userAgent .indexOf ("Chrome" ) < 0 ;          window .onload  = function (             if (isSafari){                 var  aobj = document .querySelector ('a' );                 var  href = 'http://www.test2.com/index_b.html?message=' + encodeURIComponent ('jogging, reading and writing' );                 aobj.setAttribute ('href' , href);             }else {                                  window .frames [0 ].postMessage ('jogging, reading and writing' ,'http://127.0.0.1:8082' );             }                      }                  window .addEventListener ('message' , function (e ){             var  data = e.data ;             document .querySelector ('p' ).innerHTML  = data;         }, false );      </script > </body > </html > 
http://www.test2.com/index_b.html 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 <!DOCTYPE html > <html  lang ="en" > <head > <meta  charset ="UTF-8" > <title > Document</title > </head > <body > <div > 点击获取任务</div > <p > </p > <script >         var  isSafari = navigator.userAgent .indexOf ("Safari" ) > -1  && navigator.userAgent .indexOf ("Chrome" ) < 0  ;          function  GetQueryString (name )         {              var  reg = new  RegExp ("(^|&)" + name +"=([^&]*)(&|$)" );              var  r = window .location .search .substr (1 ).match (reg);              if (r!=null )return  decodeURIComponent (r[2 ]); return  null ;         }         if (isSafari){             var  data = GetQueryString ('message' );             localStorage .setItem ('task' ,data);         }         document .querySelector ('div' ).addEventListener ('click' , function (             document .querySelector ('p' ).innerHTML  = localStorage .getItem ('task' );         }, false );      </script > </body > </html > 
如此就可以比较好的解决localStorage的跨域存储问题了。