[干货]数据交互与本地存储

数据交互与本地存储

阅读目录

  • 一:Iframe父页面与子页面之间的调用
  • 二:理解JSONP跨域技术的基本原理
  • 三:iframe之间通信问题
  • 四:iframe高度自适应的问题。
  • 五:本地存储cookie,sessionStorage, localStorage比较及使用
  • 六:window.name 实现跨域数据传输。
  • 七:使用HTML5中postMessage 实现ajax中的POST跨域问题
回到顶部

一:Iframe父页面与子页面之间的调用

专业词语解释如下:

    Iframe:iframe元素是文档中的文档。

    window对象: 浏览器会在其打开一个HTML文档时创建一个对应的window对象。但是,如果一个文档定义了一个或者多个框架

(即:包含一个或者多个frame或者iframe标签),浏览器就会为原始文档创建一个window对象,再为每个iframe创建额外的window对象,这些额外的window对象是原始窗口的子窗口。

contentWindow: 是指指定的iframe或者iframe所在的window对象。

   1. 父页面与子页面之间的调用。

现在我们可以慢慢做demo来分别讲解下,假如有iframe父页面为 iframe1.html, 父页面上有2个子页面 分别为iframe2.html 和 iframe3.html。

父页面iframe1.html代码如下:


 
 
    
    Document
    
 
 
    
    
    
父页面

子页面iframe2.html代码如下:



 
  
  Document
  
 
 
    
aaa
子页面

1.  子页面iframe2.html调用父页面 iframe1.html的元素如下代码:

    console.log($('.iframe1',parent.document));

2.  子页面iframe2.html调用父页面iframe1.html的函数如下代码:

    parent.test2();

注意:父页面iframe1.html页面 中test2方法不能放在$(function(){}), 放在里面就调用不到。

3. 子页面iframe2.html调用自身的iframe(假如父页面有很多iframe,获取自身iframe不通过id或者name属性).

    1.首先我们可以在父页面上写一个函数 用来获取页面所有的iframe,之后进行遍历,进行判断当前的window对象是否相同。如下代码:

function getFrame(f){
    var frames = document.getElementsByTagName("iframe");
    for(i=0;i){
         if(frames[i].contentWindow == f){
              return(frames[i])
          }
      }
  }

    2. 在子页面iframe2.html中如下调用父页面的方法 getFrame.

 /* 获取自身的iframe */
 var aa = parent.getFrame(this);
 console.log(aa);
 $(aa).attr("flag",true);

给iframe2设置属性 flag: true, 如下截图:

 

 4. 父页面iframe1.html调用子页面 iframe2.html的元素及函数.

如下调用有误的:

console.log(document.getElementById("iframe2").contentWindow.b());

因为iframe2.html 有可能未加载完成,所以要等iframe2加载完成后再进行调用,

所以我们需要 iframe2.onload = function(){}; 这样再进行调用。为了兼容IE,我们可以如下封装一个方法:

function iframeIsLoad(iframe,callback){
    if(iframe.attachEvent) {  
         iframe.attachEvent('onload',function(){
             callback && callback();
         });

    }else {
         iframe.onload = function(){
              callback && callback();
         }
    }
}
// 调用方式如下:
// 父页面调用子页面iframe2的方法
var iframe2 = document.getElementById("iframe2");
iframeIsLoad(iframe2,function(){
    iframe2.contentWindow.b(); // 打印出 我是子页面   
    // 父页面获取子页面iframe2的元素
    var iframeDom = $(".iframe2",iframe2.contentWindow.document);
    console.log(iframeDom);
 
});
回到顶部

二:理解JSONP跨域技术的基本原理

    Javascript是一种在web开发中经常使用的前端动态脚本技术,在javascript中,有一个很重要的安全限制,被称为"same-Origin-Policy"同源策略,这一策略对于javascript代码能够访问的页面内容作了很重要的限制,即javascript只能访问与包含它的文档在同协议,同域名,同端口的脚本进行交互;

JSONP的基本原理是:利用在页面中创建

  然后在a.js代码变为如下:

   function jsonp(){

        alert(1)

   }

  jsonp();

最后我们在域名下abc.example1.com下的a.html页面运行下可以看到弹出对话框 "1";我们可以看到引入不同域名下的js文件也能跨域执行;

2. 如果我在域名为def.example2.com下的a.js文件能否调用a.html的方法名呢?我们继续来演示这个demo;我们在abc.example1.com下的a.html引入文件如下:

其中域名为def.example2.com下的a.js内容为:jsonp(); 我们继续来运行下页面,可以看到,还是可以弹出对话框 1;

3.  如果我在外面的调用方法能否传递一个参数呢?我们继续和第二点一样,只是方法里面多了一个参数传进去即可:如下代码:

def.example2.com下的a.js内容为:jsonp("我是来测试的");abc.example1.com下的a.html文件内容为:

我们运行下页面a.html,也可以看到弹出了对话框 "我是来测试的"文案;所以,我们就可以通过这种方法来给页面中传入外站的数据;可以实现JSONP的跨域数据;

理解JSONP执行过程如下:

    首先在客户端注册一个callback(比如jsonpcallback),然后把callback名字(比如叫jsonp123456)传给服务器端,服务器端得到callback名字后,需要用jsonp123456(),把将要输出的json内容包括起来,此时,服务器生成的json数据才能被客户端正确接收;然后以javascript语法的方式,生成一个function,function的名字就是传递回来的参数jsonp123456.然后就可以在客户端直接运行调用jsonp123456这个函数了;

演示代码如下:

在域名下abc.example1.com下的a.html页面代码如下:

动态创建script标签,给script动态设置src值为域名def.example2.com,这样就实现在不同的域名下了;

如下代码:


//在def.example2.com域名下的a.js代码如下:
jsonp123456({"name":'tugenhua','age':'28','single':'yes'});

分析: 在a.html下给服务器端发送请求,并且给服务器端传递参数 jsonpcallback=jsonp123456;服务器端拿到jsonpcallback这个参数后;需要用jsonp123456(),把将要输出的json内容包括起来,此时,服务器生成的json数据才能被客户端正确接收;然后以javascript语法的方式,生成一个function,function的名字就是传递回来的参数jsonp123456.然后就可以在客户端直接运行调用jsonp123456这个函数了;

如上演示的代码; 之后分别弹出data.name;data.age;及data.single;

JSONP的优点:

它不像XMLHttpRequest对象实现ajax请求受到同源策略的限制,它在所有的浏览器都支持,

比如古老的IE6也支持,并且在请求完成后可以通过callback的方式传回结果;

JSONP的缺点:

1. 只支持get请求,不支持post请求,它只支持http跨域的请求情况,

不能解决不同域的两个页面之间如何进行javascript调用的问题; 

2. 由于它是get请求,传递的参数都拼在url后面,因此数据安全性不高;

回到顶部

三:iframe之间通信问题

1. iframe通信 分为:同域通信 和 跨域通信。所谓同域通信是指 http://localhost/demo/iframe/iframeA.html  下的a.html页面嵌套 iframe 比如: 的B.html页面,这两个页面数据进行通信,比如我想在父页面A.html 调用子页面当中的函数 我们很容易想到或者google下 ;document.getElementById('iframeA').contentWindow.b(); 这种方法,其中b 是子页面B.html中的一个函数。但是这样调用下有个问题我纠结了很久,就是既然在火狐下报这样的错误, 如下图所示:

b不是个函数 但是我在子页面明明定义了这么一个函数,那么为什么会报这样的错误呢?经过仔细分析及google,发现有这么一个问题需要理解,当iframe没有加载完成后 我就去执行这个js会报这样的错误,所以就试着在火狐下 用iframe.onload 这个函数 进行测试,果然没有报错,是正确的 所以就确定是这个问题。所以就想写个兼容IE和火狐 google写个函数 来确定iframe已经加载完成!,其实给个回调函数来调用我们上面的方法。

综合上面的思路 A.html 就可以写个这样的代码:


 
topNddddddddddddddddame
B.html 代码如下: var b = function(){ alert("B"); };

2.子页面调用父页面的函数很简单,只要这样搞下就ok了,window.parent.A();

3. 子页面取父页面元素的值: window.parent.document.getElementById("topName").innerHTML等方法。

二: iframe跨域通信。

iframe跨域访问一般分为2种情况,第一种是同主域,不同子域的跨域。 第二种是:不同主域跨域。

一、 是同主域下面,不同子域之间的跨域;可以通过document.domain 来设置相同的主域来解决。

假如现在我有个域 abc.example.com 下有个页面叫abc.html, 页面上嵌套了一个iframe 如下:

 

我想在abc域下的页面abc.html 访问 def域下的def.html  我们都知道由于安全性 游览器的同源策略的限制,js不能操作页面不同域下 不同协议下 不同端口的页面,所以就要解决跨域访问了,假如父页面abc.html 页面有个js函数:

 function test(){console.log(1);};

 我想在子页面调用这个函数 还是按照上面的同域方式调用 parent.test();这样,通过在火狐下看 已经跨域了 解决的办法是 在各个js函数顶部 加一句 document.domain = 'example.com',就可以解决了。

 abc.html代码如下:


  // 跨域 子页调用父页的 函数 (假设是下面test函数)
  document.domain = 'example.com';
  function test(){console.log(1);};

def.html代码如下:

 /*
 * 子页调用父页的方法
 */
document.domain = 'example.com';
//window.top.test();
window.parent.test();

还是这两个页面 我想父页调用子页 如下方法:

a.html代码如下:

/*
 * 跨域 父页想调用子页的的函数
 */
document.domain = 'example.com';
var iframe = document.getElementById('iframe2');
iframeIsLoad(iframe,function(){
    var obj = iframe.contentWindow;
         obj.child();
});
function iframeIsLoad(iframe,callback){
        if(iframe.attachEvent) {
            iframe.attachEvent('onload',function(){
                callback && callback();
            });
        }else {
            iframe.onload = function(){
                callback && callback();
            }
        }
 }

假如现在def.html页面有个child函数 代码如下:

document.domain = 'example.com';
function child(){console.log('我是子页');}

就可以跨域调用了 不管是子页面调用父页面 还是父页面调用子页面。一切ok!

三:是不同主域跨域;

虽然google有几种方法关于不同主域上的跨域问题 有通过location.hash方法或者window.name方法或者html5及flash等等,

但是我觉得下面iframe这种方法值得学习下,如下图所示:

[干货]数据交互与本地存储_第1张图片

域a.com的页面request.html(即http://a.com/demo/ajax/ajaxproxy/request.html)里面嵌套了一个iframe指向域b.com

(http://b.com/demo/ajax/ajaxproxy/response.html)的response.html,而response.html里又嵌套了域a.com的proxy.html。

思路:要实现a.com域下的request.html页面请求域b.com下的process.php,可以将请求参数通过url传给response.html,由response.html向process.php发起真正的ajax请求(response.html与process.php都属于域b.com),然后将返回的结果通过url传给proxy.html,最后由于proxy.html和request.html是在同个域下,所以可以在proxy.html利用window.top 将结果返回在request.html完成真正的跨域。

ok, 先看看页面结构

a.com域下有:

     request.html

     proxy.html

b.com域下有:

    response.html

Process.php

先来看看request.html页面如下:



 
   New Document 
  
 
    

这里将会填上响应的结果

点击,发送跨域请求

这个页面其实就是要告诉response.html:我要让你执行你定义好的方法GetPerson,并且要用我给你的参数'{"id" : 24}'。

response.html纯粹是负责将CallBack这个方法名传递给下一位仁兄proxy.html,而proxy.html拿到了CallBack这个方法名就可以执行了,

因为proxy.html和request.html是同域的。

response.html代码如下:



 
   New Document 
 
 
     
    
 

这里其实就是接收来自request.html的请求得到请求参数和方法后向服务器process.php发出真正的ajax请求,然后将从服务器返回的数据以及从request.html传过来的回调函数名传递给proxy.html。 

接下来看看php代码如下,其实就是想返回一个json数据:

php 
    $data = json_decode(file_get_contents("php://input"));
    header("Content-Type: application/json; charset=utf-8");
    echo ('{"id" : ' . $data->id . ', "age" : 24, "sex" : "boy", "name" : "huangxueming"}');
?>

最后就是proxy.html代码:



 
   New Document 
 
 
    
 

这里也是最后一步了,proxy终于拿到了request.html透过response.html传过来的回调函数名以及从response.html直接传过来的响应数据,

利用window.top执行request.html里定义的回调函数。

回到顶部

四:iframe高度自适应的问题。

  iframe高度自适应分为2种,一种是同域下自适应  另外一种是跨域下自适应,下面我们来看看同域下iframe高度自适应的问题。

   1. 同域下iframe高度自适应的问题:

     思路:获取被嵌套iframe元素,通过JavaScript取得被嵌套页面最终高度,然后在主页面进行设置来实现。

     假如我们demo有iframe1.html和iframe2.html 下面贴上iframe1.html代码如下:



 
   New Document 
  
 
 
 
    
 
    
 

iframe2.html代码如下:



 
   New Document 
  
 
 
 
    

就可以动态设置iframe1页面的高度为iframe2的高度了。

2. 跨域下iframe高度自适应的问题。

首先我们知道iframe跨域我们是不能用上面js方式来控制了,所以我们只能用个中间键,我们可以在a.com域下iframe1.html页面嵌套一个b.com域下的iframe2.html页面,然后我在iframe2.html页面嵌套个和iframe1.html相同域的iframe3.html页面了,这样的话 iframe1.html和iframe3.html就可以无障碍的进行通信了,因为页面iframe2.html嵌套iframe3.html,所以iframe2.html可以改写iframe3.html的href值。

 iframe1中的内容:

 iframe1.html内容主要接受iframe3.html页面传过来的内容并且去完成相应的操作。iframe1.html代码如下:

 

iframe2.html中的内容:

iframe2.html内容是怎么把值传给iframe3.html页面,刚才说了是将值传递到iframe3.html页面的href中,所以只要修改iframe的src就可以,因为不用刷新C页面,所以可以用过hash的方式传递给iframe3.html页面.iframe2.html代码如下:



 
   New Document 
  
 
 
    
    
 

可以看到 默认情况下 iframe1.html 页面我给iframe2.html的高度是200像素, 但是在iframe2.html我给iframe3.html高度是230像素,那么正常情况下是有滚动条的,那么现在我是想在iframe2.html获取滚动条的高度,把高度传给通过iframe3.html的src里面去,然后在iframe3.html页面里获取这个高度值 传给iframe1.html(因为iframe1.html和iframe3.html是同域的),所以iframe1.html能取到这个高度值,再设置下本身的高度就是这个值就ok了。iframe3.html页面的唯一功能就是接收iframe2.html页面通过href传进来的值并且传递给iframe1.html页面,可到iframe2.html页面传来的值可以通过一个定时器不停去查看location.href是 否被改变,但是这样感觉效率很低,还有个方式就是在新的浏览器中通过onhashchange事件 (IE8+,Chrome5.0+,Firefox3.6+,Safari5.0+,Opera10.6+)来监听href的改变。

iframe3.html代码如下:

这样就可以解决通过跨域实现iframe自适应高度的问题了。

回到顶部

五:本地存储cookie,sessionStorage, localStorage比较及使用

一:Cookie

1. 什么是cookie?

     Cookie是在客户端用于存储会话信息的,用户请求页面在web服务器与浏览器之间传递。每当同一台计算机通过浏览器请求某个页面时,就会发送这个 cookie。

 2. cookie的限制?

     1. Cookie的数据大小限制只能为4kb数据,如果数据长度超过4kb数据,超过后的数据将返回空字符串。

     2. Cookie是以文件形式存储在客户端计算机中,查看和修改cookie很方便,但是安全性方面不好,因此重要的数据不要使用cookie来存储。

     3. Cookie是有 有效期概念的,如果想要cookie存储多长时间,可以设置cookie的时间,一般的情况下,cookie的生命周期是在游览器关闭的时候失效。

     4. Cookie是有域的概念的,在不同的域下,cookie不能互相使用,cookie对于那个域是有效的,所有向该域发送的请求中都会包含这个cookie 的信息的,

    这个值可以包含子域(subdomain 如www.zuixiandao.cn) ,也可以不包含它(如.zuixiandao.cn, 对于所有的zuixiandao.cn的所有子域都有效). 

    如果没有明确的指定,那么这个域会被认作来自设置cookie的那个域。

     5. Cookie路径的概念:对于指定域中的那个路径,应该向服务器发送cookie,比如我们可以指定cookie只有从http://www.zuixiandao.cn/books/中才能访问,那么http://www.zuixiandao.cn的页面就不会发送cookie信息。

     6. Cookie失效时间的概念:表示cookie何时应该被删除,默认情况下,浏览器会话结束时即将删除所有的cookie,不过也可以自己设置

 删除时间的。这个值是个GMT格式的日期(Wdy DD-Mon-YYYY HH:MM:SS GMT),用于指定应该删除cookie的准确时间,因此,

 cookie可在浏览器关闭后依然保存在用户的机器上(同一个浏览器,不同的浏览器不能保存),如果设置的日期是过期的日期,那么cookie立刻删掉。

      7. Cookie安全标志 指定后,cookie只有在使用SSL连接的时候才发送到服务器。比如:cookie信息只能发送给https://www.zuixiandao.cn, 

  而http://www.zuixiandao.cn的请求则不能发送cookie。

二: javascript中的cookie

     1. Javascript中的cookie是 一系列由分号隔开的名-值对,如下面的淘宝的cookie,如下:

document.cookie = "isg=E5AA5F2CEE8AA93BB351D1601F7B218E; thw=cn; _med=dw:1920&dh:1080&pw:1920&ph:1080&ist:0; v=0; t=1292efa78d867ff6275e6c5cb971bed7";

     2. 设置cookie的超时。

         expires;   // 设置cookie的过期的时间

         以下设置 cookie 在 365天后超时;

         var date = new Date();

         date.setTime(date.getTime()+365*24*3600*1000);

         document.cookie = ‘key:value;expires =' + date.toGMTString();

下面是设置cookie, 删除cookie,及 获取cookie的封装代码如下:

// 获取所有的cookies
function getCookies() {
    var allCookies = document.cookie;
    return decodeURIComponent(allCookies);
}
// 获取指定的cookie
function getOneCookie(name) {
    var allCookies = document.cookie.split(";");
    for(var i = 0, ilen = allCookies.length; i < ilen; i++) {
        var temp = allCookies[i].split("=");
        if($.trim(decodeURIComponent(temp[0])) == name) {
            return decodeURIComponent(temp[1]);
         }
    }
    return -1;
}
// 添加cookie 有效期是一年
function addCookie(name,value,expires,path,domain,secure) {
    var curCookie = encodeURIComponent(name) + '=' + encodeURIComponent(value);
    if(expires instanceof Date) {
        curCookie += ';expires =' + expires.toGMTString();
    }else {
        var date = new Date();                
        date.setTime(date.getTime()+365*24*3600*1000);
        curCookie += ';expires =' + date.toGMTString();
    }
    if(path) {
        curCookie += "; path=" + path;
    }
    if(domain) {
        curCookie += "; domain=" +domain;
    }
    if(secure) {
        curCookie += "; secure";
    }
    document.cookie = curCookie;
 }
 // 删除cookie 
 function removeCookie(name,path,domain,secure) {
     addCookie(name,"",new Date(0),path,domain,secure);
 }

下面我们来做一个小需求,比如一个登陆页面,有 有户名,密码,记住密码,及显示cookie和删除cookie按钮。当我点击记住密码的时候,那么当我第重启开页面时候,只要输入用户名,密码会自动填充,当然我们也可以点击删除cookie按钮进行删除,如下代码:

HTML代码:

cookie介绍


JS代码如下:

Cookie的实例demo如下:

cookie的demo

三:IE用户数据;

在IE5.0中,微软通过一个自定义行为引入了持久化用户数据的概念,用户数据允许每个文档最多128kb的数据,每个域名最多1MB的数据,

要使用持久化数据,首先必须如下所示,使用css在某个元素上指定userData行为:

IE用户数据

针对IE有如下使用方法:

1. getAttribute(“key”) 获取指定的属性值。

2. load(object) 从 userData 存储区载入存储的对象数据。

3. removeAttribute(“key”) 移除对象的指定属性。

4. save(object) 将对象数据存储到一个 userData 存储区。

5. setAttribute(“key”,”value”) 设置指定的属性值。

我们继续做一个demo来演示下在IE浏览器下的存储的demo。

HTML代码如下:

IE用户数据

JS代码如下:

var dataStore = document.getElementById("dataStore");
$("#IESave").click(function(e){
    dataStore.setAttribute("name","tugenhua");
    dataStore.setAttribute("book",'111111');
    dataStore.save("bookInfo");
});
// IE下获取数据
$("#IEGet").click(function(){
    dataStore.load("bookInfo");
    alert(dataStore.getAttribute("name"));
    alert(dataStore.getAttribute("book"));
});

// IE下删除数据 
$("#IERemove").click(function(){
    dataStore.removeAttribute("name");
    dataStore.removeAttribute("book");
    dataStore.save("bookInfo");
});

IE浏览器下的demo如下:

使用IE浏览器下查看效果 请点击我!!

四:sessionStorage 和 localStorage 

Html5新增了两个本地存储数据,分别是sessionStorage 和 localStorage.

浏览器支持程度如下:

[干货]数据交互与本地存储_第2张图片

注意:IE8 及 以上都支持 web storage。

   sessionStorage: 将数据保存在session对象中,所谓session,指用户浏览某个网站时,从进入网站到浏览器关闭的这段时间,也就是用户浏览这个网站所花费的时间。

       生命周期:指只在当前的窗口有效,打开一个新的同源窗口,或者说重启浏览器都失效。

       数据大小:可以保存5MB甚至更多。

   localStorage: 将数据保存在客户端本地的硬件设备(通常是指硬盘,但也可以是其他硬件设备),即使浏览器被关闭了,该数据依然存在,下次打开浏览器访问网站时仍然可以继续使用。但是,数据保存是按不同的浏览器分别进行的,也就是说,如果打开别的浏览器,是读取不到在这个浏览器中保存的数据的。

     生命周期:数据一直保存在硬盘中。持久性保存(但是不同的浏览器保存的数据,是不能通用的)。

     数据大小:可以保存5MB甚至更多的数据。

    1. cookie 与 sessionStorage 及 localStorage的区别;   

        共同点:都是在客户端存储数据,且是同源的。

    区别:

存储大小不一样;cookie存储数据最大只能为4kb,而sessionStorage与localStorage可以保存5MB甚至更多数据。

  Cookie数据始终在同源的http请求中携带,即cookie在浏览器与服务器之间来回传递,而sessionStorage与localStorage不会自动发给服务端,仅在本地保存。

数据有效期不同;sessionStorage仅在当前浏览器窗口未关闭之前有效(同源的新窗口不生效),localStorage仅在当前的浏览器下永久生效(不同的浏览器不能共享数据),不管关闭了 重新打开的 还是生效的。Cookie只在设置的cookie过期时间之前一直有效,即使窗口或者浏览器关闭,或者打开新的同源窗口。

作用域不同;sessionStorage不在不同的浏览器窗口中共享,即是同一个页面,localStorage在所有的同源窗口中都是共享的(只在相同的浏览器下),cookie在所有的同源窗口都是共享的(仅在同一个浏览器中)。

      SessionStorage与LocalStorage他们都拥有相同的方法;

      1. setItem存储value

         用法:.setItem( key, value),代码如下:

         localStorage.setItem(key,value):将value存储到key字段

      2. getItem获取value

          用法:.getItem(key) 代码如下:

          localStorage.getItem(key):获取指定key本地存储的值

      3. removeItem删除key

          用法:.removeItem(key),代码如下:

          localStorage.removeItem(key):删除指定key本地存储的值

      4. clear清除所有的key/value

          用法:.clear(),代码如下:

          localStorage.clear();  清除所有的数据(firefox除外)

      它将删除所有同源的本地存储的localStorage数据

      而对于Session Storage,它只清空当前会话存储的数据。

      sessionStorage也有上面一样的方法;

下面我们来使用sessionStorage及 localStorage 来练习下,来做个demo。如下:

HTML代码如下:

web Storage实列

页面上一个input输入框,当我点击 保存数据 按钮后 分别使用sessionStorage和localStorage 把值保存起来,当我点击 读取数据 按钮后 读取数据,分别在不同的浏览器或者新的同源窗口 或者关闭浏览器窗口 重新打开新窗口,来分别看看之间的区别,区别上面已经总结了,下面我们来看看JS代码如下:

如上的代码,我们现在继续来看看效果如下:使用

sessionStorage效果请点击:

使用localStorage效果请点击:

我们还可以做一点复杂的应用,比如如下一个表格有一些字段,比如姓名,email,tel,及备注字段,我们先保存到本地去,然后根据姓名这个字段进行搜索就可以搜索到数据到,我们可以称为这是简单的本地数据库,如下代码:

姓名:
EMALL:
电话号码:
备注:
保存

检索:

JS代码如下:

//  保存数据
$("#save").unbind('click').bind('click',function(){
     var data = new Object;
     data.name = $("#name").val();
     data.email = $("#email").val();
     data.tel = $("#tel").val();
     data.memo = $("#memo").val();
     var str = JSON.stringify(data);
     localStorage.setItem(data.name,str);
     alert("数据已经保存");
 });

 // 检索数据
 $("#find").unbind('click').bind('click',function(){
      var find = $("#file").val();
      var str = localStorage.getItem(find);
      var data = JSON.parse(str);
      var result = "姓名:" + data.name + "
"; result += "Email: " + data.email + "
"; result += "tel:" + data.tel + "
"; result += "备注:" + data.memo + "
"; $("#msg").html(result); });

demo如下效果:

请点击查看:

回到顶部

六:window.name 实现跨域数据传输。

Window.name 中的name值在不同的页面(甚至不同的域名)加载后依旧存在,并且数据量可以达到2MB。

Window.name 数据传输的基本原理:

同域下:Name在浏览器环境中是一个全局/window对象的属性,且当在ifrmae中加载页面时,name的属性值依旧保持不变。

比如我们在同域下abc.example.com下 有2个页面 app.html 和 data.html

 App.html页面代码嵌套一个iframe data.html页面,代码如下:

其中data.html 页面 使用一个window.name = “111”;来保存数据。

   现在我们接下来在app.html页面 如何来调用同域下的data.html下的window.name的数据,首先我们先要获取到这个iframe,然后判断iframe是否加载完,加载完后就获取这个iframe中的window.name, 

App.html JS的代码如下:

function iframeIsLoad(iframe,callback){
    if(iframe.attachEvent) {
         iframe.attachEvent('onload',function(){
          callback && callback();
         });
    }else {
        iframe.onload = function(){
         callback && callback();
        }
    }
 }
var iframe = document.getElementById("iframe");
// 同域下
iframeIsLoad(iframe,function(){
    var data = iframe.contentWindow.name;
        alert(data);
 });

2. 跨域下:

   现在我们使用hosts文件来绑定2个IP 来演示下跨域的情况,在hosts文件绑定如下:

   127.0.0.1  abc.example.com  和 127.0.0.1 def.example.com

   我们现在在 abc.example.com 新建一个app.html页面 里面还是嵌套一个 def.example.com域下的 data.html页面,代码如下:

   App.html代码如下:

如果我们还是和上面的方式取数据的话 明显报错跨域了,现在我们是使用window.name解决跨域下数据的传输,那么我们可以使用一个同域abc.example.com下的代理页面proxy.html来做处理,通过在def.example.com域下的data.html页面加载一个与abc.example.com同域下的proxy.html页面, 将该目标页面设置iframe的name属性,因为app.html 与 proxy.html是在同一个域下,所以我们可以获取到。

在app.html页面 JS代码如下:

function iframeIsLoad(iframe,callback){
    if(iframe.attachEvent) {
        iframe.attachEvent('onload',function(){
             callback && callback();
        });
    }else {
        iframe.onload = function(){
             callback && callback();
         }
     }
 }       
var iframe = document.getElementById("iframe");
var state = 0;
// 跨域下
iframeIsLoad(iframe,function(){
   if (state === 1) {
        var data = iframe.contentWindow.name;    // 读取数据
        alert(data);    //弹出111
   } else if (state === 0) {
        state = 1;
        iframe.contentWindow.location = "http://abc.example.com/demo/tugenhua0707/storage/proxy.html";    // 设置的代理文件
   }  
});

当然如上:我们如果name数据已经拿到了的话,以后不需要的话,我们可以销毁掉,清空等操作。

回到顶部

七:使用HTML5中postMessage 实现ajax中的POST跨域问题

浏览器支持程度:IE8+,firefox4+,chrome8+  opera10+

     1. 首先,要想接收从其他的窗口发过来的消息,就必须对窗口对象的message事件进行监听,如下代码:

          window.addEventListener(“message”, function(){},false);

     2. 其次,需要使用window对象的postMessage方法向其他窗口发送消息,该方法定义如下所示:

         otherWindow.postMessage(message, targetOrigin);

该方法使用2个参数,第一个参数为所发送的消息文本,但也可以是任何javascript对象,第二个参数是接收消息的对象窗口的url地址

(比如:http:127.0.0.1:8080/) , 但是我们也可以在url地址字符串中使用通配符”*”, 指定全部的域下,但是我们还是建议使用特定的域名下,

otherWindow为要发送窗口对象的引用。

Demo演示:

     假如现在我在hosts文件下 ,绑定2 个域名如下:

     127.0.0.1       abc.example.com

     127.0.0.1        longen.example.com

现在假如在abc.example.com域下有一个abc.html页面,在longen.example.com域下有def.html页面,现在我是希望这2个不同域名下的页面

能互相通信,abc.html代码如下:

目标iframe传来的信息:

暂无信息

JS代码如下:

var win = document.getElementById("iframe").contentWindow;     
document.getElementById("submit").onclick = function(e){
    e.preventDefault();
    win.postMessage(document.getElementById("message").value,"http://longen.example.com"); 
}  
         
window.addEventListener("message",function(e){
     e.preventDefault();
     document.getElementById("test").innerHTML = "从" + e.origin + "那里传过来的消息:\n" + e.data;
},false);

Def.html代码如下:

HTML代码:

暂无信息。

JS代码如下:

var parentwin = window.parent; 
window.addEventListener("message",function(e){
       document.getElementById("test2").innerHTML = "从父窗口传来的域" +e.origin + ",和内容数据:" + e.data;  
       parentwin.postMessage('HI!你给我发了"'+e.data+'"。',"http://abc.example.com");
},false);

当我点击abc.html页面后,可以看到效果如下,从def.html返回内容了。如下:

[干货]数据交互与本地存储_第3张图片

我们需要知道如下几条信息:

1. 通过对window对象的message事件进行监听,可以接收消息。

2. 通过访问message事件的origin属性,可以获取消息的发送源。

3. 通过访问message事件的data属性,可以取得消息内容。

4. 使用postMessage方法发送消息。

5. 通过访问message事件的source属性,可以获取消息发送源的窗口对象(准确的说,应该是窗口的代理对象)。

有了上面的基本知识点,我们可以延伸为实现ajax POST跨域的问题。

2. 使用postMessage 知识点解决 ajax中POST跨域问题。

 原理:原理也很简单,假如我们的域名abc.example.com下的abc.html页面需要发ajax请求(跨域,域名为longen.example.com)下,那么我们还是先跨页面文档的形式,和上面一样,我们可以现在longen.example.com下 建立一个页面,比如叫def.html. 那么我们现在还是在 abc.html 页面嵌入一个隐藏域iframe src路径指向longen.example.com域下def,html页面。过程还是和跨文档类似,

 只是现在在def.html页面中 在window.onmessage 事件内写ajax请求即可,如下代码:

abc.example.com下的abc.html页面如下:

html代码和上面一样,下面是JS代码:

var win = document.getElementById("iframe").contentWindow;      
document.getElementById("submit").onclick = function(e){
      e.preventDefault();
      win.postMessage(document.getElementById("message").value,"http://longen.example.com/"); 
}     
window.addEventListener("message",function(e){
    e.preventDefault();
    alert(typeof e.data)
    var json = JSON.parse(e.data);
     console.log(json);
    alert(json.url)
},false);

def.html代码如下:

JS代码如下:

//获取跨域数据  
window.onmessage = function(e){  
     $.ajax({
          url: 'http://longen.example.com/webSocket/test.php',
          type:'POST',
          dataType:'text',
          //data: {msg:e.data},
          success: function(res) {
               var parentwin = window.parent;  
               parentwin.postMessage(res,"http://abc.example.com");//跨域发送数据  
          }
      });
 };

test.php代码如下:

php 
    $data=array(  
     url =>1,
      name =>'2',
      'xx-xx'=>"xx"
 );
 echo json_encode($data);
?>

如上实现方式 就可以实现ajax post跨域了。

你可能感兴趣的:([干货]数据交互与本地存储)