JavaScript 通信 / Ajax

Ajax

表单提交

在HTML中提供了表单提交的功能,我们可以通过表单把数据从前台提交到后台

<body>
  <form action="02.php" method="post">
  <!-- action表示的是提交的后台地址,method代表的是提交的方式时get还是post -->
    账号:<input type="text" value="提交内容"><br>
    密码:<input type="password" ><br>
    <input type="submit" value="提交">
  </form>
</body>

在HTML的DOM中,设置submit()事件,通过为按钮或其它元素同样可以触发表单提交的事件

<body>
  <form id="user" action="02.php" method="post">
    账号:<input type="text" value="请输入账号"><br>
    密码:<input type="password" value="请输入密码"><br>
    重置:<input type="reset" value="重置"><br>
    <button id="btn">提交</button>
  </form>
<script>
  var btnObj=document.getElementById("btn"),
      formObj=document.forms[0];//forms表示获取页面中所有的表单,返回一个数组
  btn.onclick=function(){
      formObj.submit();
      console.log("提交成功")
  }
</script>
</body>

通过from表单提交数据不需要依赖js引擎,浏览器本身就可以实现,但这样也会产生一个问题,用户提交数据信息的时候需要刷新整个页面,这就大大降低了用户体验

Ajax

什么是Ajax

Ajax的诞生解决了上述的问题,Ajax代表的是:Asynchronous Javascript And XML,也就是异步,javascript和XML,Ajax不是一门编程语言,而是一种用于创建更好更快交互性更强的web应用技术,可以通过少量的浏览器和服务器 之间的数据交互实现页面的部分刷新,需要注意的是在使用了Ajax技术后,用户的请求数据是间接通过Ajax引擎来发出的,而不是直接通过浏览器来发出,服务器返回的数据也是传回到Ajax引擎

需要注意的是Ajax虽然在使用时的优点显而易见,但同时缺点也是有的:

  1. 对搜索引擎不友好
  2. 用户无法使用回退获得之前的页面

我们可以对比一下传统的提交方式和使用Ajax技术的提交方式的不同:

1430231-31e3d2c74bd828e3.png

我们来举一个栗子:表单验证

1430231-76865557eaa44c87.png
1430231-ca33fe1730451dae.png

Ajax引擎

Ajax的精华部分就是它的Ajax引擎,那么什么是Ajax引擎呢?就是XMLHttpRequest对象,除了已经入土的IE5,其它现代浏览器都支持该对象,同时它也是一个JavaScript对象,它负责发出请求和接收响应

在IE5和IE6中Ajax引擎是ActiveXRequest,所以我们需要做兼容性问题

<script>
  function createAjax(){
     var xhr;
     window.XMLHttpRequest?xhr=new XMLHttpRequest():xhr=new ActiveXObject("Msxml2.XMLHTTP");
     return xhr;
  }
</script>

使用Ajax

创建Ajax引擎

也就是XMLHttpRequest对象,做兼容性判断

<script>
    function createRequst() {
      return window.XMLHttpRequest ? new window.XMLHttpRequest() :
                    new window.ActiveXObject('Microsoft.XMLHTTP');
    }

    console.log(createRequst());//在IE7-中返回的是一个object对象
</script>

XMLHttpRequest对象的方法和属性

20161213193531.png

我们找几个比较主要的说一下,

  • onloadstart 请求开始时触发的事件

  • onloadend 请求结束时触发的事件

  • ontimeout 请求超时时触发的事件

  • onreadystatechange 请求状态改变时触发的事件

  • readyState 请求状态

  • status 服务器返回的状态码

  • timeout 设置请求的时间,当请求的时间超过我们设置的时间时,自动将请求注销掉

  • withCredentials 是否要求证书(例如12306)

  • responseText 在非XML格式下返回的数据

建立连接

举一个栗子:

<script>
    var xhr=createRequst();//封装的函数
    xhr.open("GET","data.php",true);//如果是使用GET方式提交数据那么需要在URl后添加?然后把键值对之间以&符号    链接拼接在?后面,如果是使用POST获取数据,那么我们要将参数传递到send中,键值对与键值对之间使用&符号拼接
</script>

在建立连接时,我们要调用open方法,open方法有三个参数

open(type,url,isAsync),这几个参数分别代表:

  1. type,请求方式,GET还是POST,当然还有其它方式,如DELETE,用来删除服务器上的数据,但不常用,这里不列举了
  2. url ,请求的服务器的地址
  3. isAsync ,请求是否异步,默认为true,也就是异步请求
GET和POST

这里我们需要了解一下同样是请求后台数据,GET和POST的区别,在之前我们会想到的是:

  1. GET请求是体现在url地址栏中的,安全性比较差,POST是在request body提交的,安全性较高
  2. GET请求的参数是会被保存在地址栏中的,而POST不会,也就是说在我们使用后退键时,使用GET请求会保存在地址栏中
  3. 使用POST的时候,如果使用后退键会重复提交,而GET则不会
  4. POST方式理论上是没有大小的限制的,而GET方式由于浏览器会限制地址栏的长度,一般限制为2K字符以内,4K大小以内,超过部分不予解析
  5. 对于参数类型,GET方式只支持ASCLL编码格式,而POST则没有限制(使用前最好将传入的数据进行编码转换)

但是,在看到一篇大神的文章之后,以上的区别统统显的不重要了,我们来开始学习怎样高逼格的说明这俩者的不同

我们都知道,无论是GET还是POST请求,都是建立在HTTP协议之上的,而HTTP协议又是建立在TCP协议之上的,也就是HTTP协议规定的数据在万维网中传输的的规定,那么说白了GET和POST只是两种不同的TCP链接,只是由于浏览器的规定设置导致了有一些差异,在本质上并没有什么区别,实际上真正的差别在于,GET和POST在传输数据的过程中,GET会产生一个TCP数据包,而POST会产生两个数据包

浏览器在发送GET请求时是将http header和data一起发出,服务响应200,而在发送POST请求时。浏览器会先发送http header,服务器响应100 continue,再发送data,服务器响应200,也就是说,GET方式提交数据是一次性的,而POST第一次先告诉服务器我要请求数据,第二次再将数据提交过去

所以这里由于POST是两次请求,耗时会增加,这也是雅虎优化建议中为什么提出,我们尽量将页面中使用POST的方式改为GET来提升响应速度,但是,在网络性能好的情况下,使用GET和POST的时间差别几乎没有,在网络较差的情况下,两次打包会大大提升数据的完整性,而且不是所有浏览器都是两次打包的,FF就是使用一次打包

GET和POST同样不安全,通过POST加密的数据会被抓包工具截取,或者在F12中Network中Headers中获取,如果有要求使用加密同样需要通过加密方式进行加密

监听状态信息

继续上面的栗子:

<script>
xhr.onreadystatechange=function(){
      if(xhr.readyState===4){//判断请求状态是否是已经完成
        if(xhr.status>=200&&xhr.status<=300||xhr.status===304){//判断服务器是否返回成功200,304
          console.log(xhr.responseText);//接收xhr的数据,xhr.responseText
        }
      }
    }
</script>

这里有一些需要我们了解的东西

  1. readyState 请求的状态码

    0: 表示请求未初始化,也就是没有建立open请求

    1: 表示建立open()请求,正在发送请求

    2: 表示请求已经接收,open()方法已经完成,已经收到全部响应内容

    3: 表示请求处理中,正在解析响应内容

    4: 表示请求已经完成,响应也已经就绪,也就是说响应内容已经解析完成,可以在客户端进行调用了

  2. status 服务器返回的状态码,有几种常见的类型:

    以1开头代表请求已经接受

    以2开头代表请求已经成功

    1. 200,请求成功

    以3开头代表网页重定向,常见的几个:

    1. 304,代表浏览器缓存可以继续使用,服务器没有返回数据,直接从浏览器中获取数据

    以4开头代表请求错误 ,检查是不是url输入错误或者是后台人员接口给错了

    1. 404,无法找到指定的资源,也就是url地址错误
    2. 405,请求方法对请求资源不适用
    3. 403,请求不允许

    以5开头代表服务器错误,处理方法,直接通知后台人员,让他们进行处理

如何解决服务器返回304

浏览器有默认的缓存机制,在第一次向服务器请求数据的时候,在发现页面中存在文件请求时会发出请求,并将这些请求缓存在本地,在第二次向服务器发送请求的时候,在请求头中发送一个Last- Modified,它包含了上一次从服务器获得数据的日期。如果服务器判断从这个日期起服务器中数据没有进行修改,那么直接返回304的状态,不再重新发送数据,此时用户仅仅是获取了304状态码,不会再次请求数据,而是直接从本地读取缓存

最简单的方法就是直接在url地址中添加一个随机数的时间戳,例如:/Home/GetMusic?id=1+时间戳

在前端有个设置可以解决读取缓存的方法,设置meta标签的属性

<meta http-equiv="prgma" content="no-cache">

设置Ajax默认禁止缓存

<script>
    var xhr=createRequst();//封装的函数
    xhr.open("GET","data.php",true); 
    xhr.onreadystatechange=function(){
      if(xhr.readyState===4){
        if(xhr.status>=200&&xhr.status<=300||xhr.status===304){
          console.log(xhr.responseText);
        }
      }
    }
    xhr.setRequsetHeader("Content-type":"application/x-www-form-urlcoded");
    xhr.setRequsetHeader("Canhe-Control","no-cache");//阻止浏览器读取缓存
    xhr.send();
</script>

在JQ中设置Ajax的cache属性,参数为Bollean属性,默认为ture,设置为false

发送请求头

在使用POST发送页面的时候需要注意的是,要发送请求头,格式如下:

xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
//设置请求头格式为仿照form表单提交

在发送Ajax请求时默认发送的请求头格式为文本格式,如果用来提交表单数据会报错,所以需要我们认为的设置请求头格式,以上的代码的作用就是告诉服务器我们发送的是form表单格式的数据

发送请求

<script>
    //继续上面的代码
    xhr.send();
</script>

这里我们注意一个问题,关于send()的位置问题,之前我们一直把send()放在监听事件状态之前,这样写在默认的异步状态下是没有问题的,但如果是在同步的状态下看,是会报错的,这就涉及到了执行顺序的问题,我们是需要先准备好怎么样接收数据,然后才能对数据进行接收

JSON数据

json是一种键值对模式的字符串,其中的键和值都是用双引号进行包裹,由于json的轻量和便于使用,现在大部分公司使用的都是json格式的数据,我们可以举几个例子来看一下

例如:

var str={"name":"Tom","age",18}//如果值是数字的话可以不使用双引号包裹

我们之前写对象的时候有时候会写如下的格式:

var obj={
  "name":"tom",
  "age":18
}

但需要注意的是,这种格式输出的仍然是对象,在js进行解析的时候,其中的键的双引号会被去除

我们来看一个比较复杂的json格式

var people =

{
"name":"Tom",
"programmers": [

{ "firstName": "Brett", "lastName":"McLaughlin", "email": "brett@newInstance.com" },

{ "firstName": "Jason", "lastName":"Hunter", "email": "jason@servlets.com" },

{ "firstName": "Elliotte", "lastName":"Harold", "email": "elharo@macfaq.com" }

]

}
JSON的方法

在浏览器中为我们提供了两种json数据格式转化的方法

  1. JSON.parse(ison),该方法表示将接收到的json数据格式转化为对象格式,需要重点注意的是在使用JSON方法时,必须是键值对使用双引号包裹,所以外层的需要是单引号

  2. JSON.stringify(obj),该方法表示将js中的对象转化为json格式的字符串

  3. 这里其实还有一个方法可以解析json格式的字符串,eval(),这个方法比较特殊,W3C对它的介绍是,很强大的一个功能,但是运用的很少,这是因为eval()方法本身会自动执行字符串中的方法,如果我们直接接收没有验证过的返回信息就会很容易遭到攻击,例如:

    <script>
      var str={"name":alert("弹出")};
      var o=eval(str);
      //在执行上述代码时会自动弹出alert提示框,因为在使用eval时已经执行了字符串内部的逻辑代码
    </script>
    

JQuery中的Ajax使用

在JQuery中对Ajax方法进行了封装,JQuery的Ajax封装是非常强大的,在其他框架也大量借鉴了该方法,下面我们来看一下在JQuery中是如何使用Ajax的

比较简单方法:

<script>
      $(function(){
          $("#btn").on("click",function(){
             $.post("02.php",{name:"Tom",age:18},function(data){
                console.log(data)
             },'json')
          })
      })
      //相对应的还有GET和getJSON等其它方法,基本套路都一样
 </script>

下面的是我们经常用到的,同样也是在其他框架中被参考的方法$.ajax

 <script>
      $.ajax({
        type:"get",//设置请求的方式
        url:"02.php",//设置请求的地址
        data:{name:"tom",age:18},//设置发送的参数
        dataType:"json",//请求的数据类型,自动转化为对象
        async:true,//设置是否异步,默认为true
        cache:false,//设置浏览器是否缓存该页面,默认为true
        timeout:300,//设置请求超时时间
        beforeSend:function(xhr){//请求开始前回调该函数
          console.log("请求开始前");
          //return false  如果在请求开始前直接return等于阻止了ajax请求
        },
        success:function(result,status){//请求成功时回调该函数,,result代表返回的数据,status为状态描述
          console.log("请求成功了");
        },
        error:function(xhr,status,error){//请求失败时回调该函数,xhr为 XMLHttpRequest对象,status为错误信息,error表示捕获的错误对象
          console.log("请求失败,"+xhr.status);
        }
      })
      //以上只是我们常用的一些方法和参数,JQuery中还封装了很多其它的方法和参数,包括上面提到的$.get和$.post等方法都是该方法的变种
    </script>

Ajax的封装

我们过这里模拟JQuery中的Ajax方法,对其进行简单的封装,不多说,直接上代码

<script>
        function formatData(data) {//格式化数据的方法
            var ret=[];
            for(var key in data){
              //有时候传入的可能是汉字,所以需要利用encodeURIComponent转化成编码格式
              //encode方法废弃了,现在提供的是encodeURLConponent方法
                ret.push(encodeURIComponent(key)+"="+encodeURIComponent(data[key]));
            }
            //伪造不同url,防止获取缓存的数据(http状态码304)xhr
            ret.push(("="+new Date().getTime()))
            return ret.join("&");
        }
  
        function createRequst(){//创建Ajax引擎对象
            return XMLHttpRequest()?new XMLHttpRequest():new ActiveXObject("Msxml2.XMLHTTP")
        }
        
         function jsonp(option){
            //判断用户传入的参数
            if(!option||!option.url||!option.callback){ 
                console.error("参数异常");
                return;
            }
            //如果用户参数传入正确,创建script标签,添加到head标签中
            var scriptElement=document.createElement("script"),
                headElement=document.getElementsByTagName("head")[0];
            headElement.appendChild(scriptElement);

            //注意jsonp创建的函数是全局函数,为了防止代码污染,起特定的名字
            var fnName=("jsonp_"+Math.random()).replace(".","");
            option.data[option.callback]=fnName;//给用户传入的向后台发送的data数据中添加一个option.callback属性,并赋值为我们自定义创建的函数名,让后台接收我们的函数名,后台才能返回给我们数据

            window[fnName]=function(data){
                if(option.timeout){//用户如果设置了超时时间,在接收到数据后将计时器清除
                    window.clearTimeout(scriptElem.timer);
                }
                    delete  window[fnName];//删除全局函数
                    headElement.removeChild(scriptElem);//删除创建的script标签
                    option.success && option.success(data);
                }
                if(option.timeout){//如果用户设置了超时时间,设置计时器,在用户设置的超时时间到达后如果该函数执行,说明超时,那么执行其中的代码
                    scriptElement.timeout=window.setTimeout(function(){
                        delete global[fnName];
                        headElem.removeChild(scriptElem);
                        option.fail && option.fail({"message": "请求超时"});
                    }, option.timeout)
                }
                scriptElem.src = option.url + '?' + formatData(option.data);//执行跨域请求,跨域的时候不需要其它参数,所以data中的数据就是callback和它的值
            }

        }
  
        $.extend({
            AjaxSetting:{//设置用户默认输入的各项参数
                url:"",
                type:"GET",
                dataType:"json",
                async:true,
                success:null,//成功后执行的函数
                fail:null,//失败后执行的的函数
                contentType:"application/x-www-form-urlencoded;charset=UTF-8"//模拟表单提交的请求头

            },
            ajax:function(url,option){//在JQuery中使用的两个参数,这里仿照JQuery写法

                var context,xhr;

                if(typeof url==="object") {//判断url类型,如果用户直接传入一个对象,说明没有单独传入URL地址,那么我们执行下面的代码
                    option=url;
                    url=null;
                }else{//如果用户单独传入了url地址,那么我们执行下面的代码
                    option.url=url;
                    url=undefined;
                }   

                if(!option||!option.url||!option.success){//判断用户是否输入option,option中的url和success是我们设置为默认必须的,所以在用户传入时就进行判断
                    console.error("参数传入异常");
                    return ;
                //如果用户传入的参数异常,那么我们弹出异常,并且直接返回
                }
                // 通过JQuery中的extend方法获取默认设置
                 $.extend($.AjaxSetting, context);
                // 通过JQuery中的extend方法获取用户设置,覆盖或新增默认的设置
                 $.extend(option, context);

                 if(context.dataType.toLowerCase()==="jsonp"){//判断用户是否要求跨域
                        jsonp(context);//如果是的话执行jsonp的方法
                 }else{//否则的话执行Ajax函数
                    xhr=createRequst();//通过createReqyst方法执行函数
                    xhr.onreadystatechange=function(){
                        if(xhr.readyState==4){
                            if(xhr.status>=200&&xhr.status<300||xhr.status==304){
                                var data=context.dataType.toLowerCase()=="json"?
                                    JSON.parse(xhr.responseText):
                                    xhr.responseText;
                              //判断用户需求什么格式的数据,如果是json的数据,将请求来的数据进行转换
                                context.success&&context.success(data,context,xhr);
                              //判断用户是否输入了success方法,如果有的话执行success方法,如果我们直接执行的                                话,由于上面设置了success为null,用户如果没有设定会报错
                            }
                        }else{
                            context.fail && context.fail({"message": "请求超时."})
                        }
                    }
                 if(context.type.toUpperCase()=="GET"){
                    xhr.open("GET",context.url+"?"+formatData(context.data),context.async);
                   //利用formatData方法格式化数据
                    xhr.send();
                 }else{
                    xhr.open("POST",context.url,context.async);
                    xhr.setRequestHeader("contentType",context.contentType)
                    xhr.send(formatData(context.data));
                 }
                 }

            }
        })
</script>

Ajax轮询和长连接

Ajax轮询和长连接都是为了实现页面的实时刷新,但是需要注意,如果在不是必要的情况下尽量不要使用这两种方法,大量的不间断的数据请求对前台和后台都是非常有压力的

  1. Ajax轮询

    客户端定时向服务器发送Ajax请求,服务器在返回数据后断开连接,轮询能够实现页面的实时刷新,但是缺点也很明显,定时的发送数据大部分是没有意义的,而且占用额外的服务器资源

    <script>
     function Ajax(){
         setInterval(function(){
                 var xhr=new XMLHttpRequest();
                     xhr.open("open","url",true);
                     xhr.onreadystatechange=function(){
                         if(xhr.readyState===4){
                             if(xhr.status>=200&&xhr.status<=300||xhr.status==304){
                                 console.log(xhr.responseText)
                             }
                         }
                     };
                     xhr.setRequestHeader("Content-type","qpplication/x-www-form-urlencoded");
    
             },5000)
         }   
    </script>
    

    代码实际上很简单,就是调用计时器,每过一段时间向后台发送一次请求

  2. long-polling

    所以为了能够使页面及时刷新,并且改善轮询存在的弊端,我们一般使用的是长轮询的方法,也就是ling-poling

    <script>
     $(function(){
         (function longPolling(){
             $.ajax({
                 url:"01.php",
                 type:"get",
                 datatype:"json",
                 timeout:5000,
                 error:function(xml,status,eror){
                      //可以选择报请求超时的错误,不过一般不这么做
                      longPolling();
                      
                 },
                 success:function(data,status,xhr){
                     console.log(data);
                     //如果有数据返回,那么将数据添加到页面
                     longPolling();
                 }
             })
         })()
     })
    </script>
    

    Ajax长轮询需要后台写相应的代码来配合完成

模板引擎

什么是模板引擎,说白了就是在字符串中有几个变量待定

例如:

//这里用到的是attTemplate模板引擎
<script type="text/template" id='template01'>//为了防止script对内容进行解析,将script的type属性变为非javascript即可,改为template主要是为了增加代码的可读性
        <tr>
            <td><%=name%></td> //<%= %>代表输出值
            <td><%=skill%></td>//在这里<%= %>中的skill代表的就是我们设定的待定的变量
            <td><%=wife%></td>
            <td>
                <% for(var i=0;i<friends.length;i++){ %>  // <%  %>里的内容代表的是输出的逻辑语句
                <a><%=friends[i]%></a>
                <% }%>
            </td>
        </tr>
</script>

我们可以在写一个完整的:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <script src="js/template-native.js"></script>//导入模板引擎js文件
  <script type="text/template" id="template">
    <% for(var i = 0;i < posts.length; i++) {%> 
      <%   var post = posts[i]; %>
      <% if(!post.expert){ %>
        <span>post is null</span>
    <% } else { %> 
        <a href="#"><%= post.expert %> at <%= post.time %></a>
    <% } %>
    <% } %>
  </script>
</head>
<body>
<script>
  
    var data = {
    "posts": [{
        "expert": "content 1",
        "time": "yesterday"
    },{
        "expert": "content 2",
        "time": "today"
    },{
        "expert": "content 3",
        "time": "tomorrow"
    },{
        "expert": "",
        "time": "eee"
    }]
  };

    var str=template('template',data);//artTemplate模板引擎的使用就是调用template方法,传入模板的id和变量的值
    console.log(str)
</script>
</body>
</html>

封装方法主要是使用了string的方法和正则进行匹配,下面写一下大概的封装

<script>
    function template(templateStr,data){//传入两个值,templateStr代表模板的字符串,data代表传入的变量对象

        var reg = /<%=\s*([^%>]+\S)\s*%>/,//定义正则匹配<%= %>
            result;

        while(result=reg.exec(templateStr)){//根据正则的exec方法的属性如果没有符合的返回null来确定循坏停止的条件

            var matchString=result[0],//根据exec方法返回的是<%= %>这部分的字符串

                matchWord=result[1];//根据exec方法返回的是<%= %>中的字符,也就是我们传入的data中的键

            templateStr=templateStr.replace(matchString,data[matchWord]);
            //调用字符串的rplace方法,符合的目标进行替换
        }
        return templateStr;
    }     

</script>

跨域

什么是跨域

处于安全性的考量,现代所有的浏览器都遵循同源策略,同源策略不允许Ajax获取其它页面的数据,我们通过某种方式来获取其它网页的数据的方式就是跨域

同源策略

简单来说就是在两个网页域名,端口,协议任意不同的情况下,A网页无法获取B网页的数据,举一个例子来说明:

2016-12-22_200002.png
http://www.example.com/dir/page.html
http://www.example.com/dir2/other.html  //同源
http://example.com/dir/other.html   //不同源,域名不同
http://v2.www.example.com/dir/other.html    //不同源,域名不同
http://www.example.com:81/dir/other.html    //不同源,端口不同

注意,同一域名下的不同服务器获取数据也是跨域,例如两台电脑的IP地址不同,A不能直接获取B电脑服务器的数据

如果是非同源那么会受到以下限制

  1. cookie, localStorage和indexDB无法读取

  2. DOM无法获取

  3. AJAX请求可以发送,但是无法获取响应

跨域的方式

单向数据请求

JSONP

什么是JSONP,很多人会把jsonp和Ajax搞混,或者认为jsonp是Ajax提供的跨域方法,但特别需要注意,这两者是相互独立的


2874363108-5abc8563bb414_articlex.png

jsonp的本质可以认为是src属性是不受同源策略的限制,可以获取其它域的数据,利用src能够跨域获取数据的特性来实现我们从其它的网站获取数据,但是必须是在该网站配合的前提条件下
实际在之前的很多操作中我们已经使用到了src能够跨域的这个特性,例如我们在img中插入一张图片,可以直接把图片的地址复制到src中

 <img src="https://www.baidu.com/img/bd_logo1.png">

下面我们来举一个jsonP跨域的例子:

<script type="text/javascript" src='http://192.168.18.38/2016-8-22/coding/cross/05.jsonP.php?callBack=sayhi'>
</script>
<script type="text/javascript">
   function sayhi(data) {//参数data就是我们要获取的跨域的数据,在拿到之后可以配合模板引擎在页面中放置
       console.log(data);//sayHi方法会自执行,因为在后台传送数据时会用括号将callback的值包裹起来
   }
  //后台在接收到callBack后,湖区到sayhi的名称,返回sayhi(”(“+data+”)“);所以我们接收的函数的参数就是我们要获取的数据
</script>

​ 在JQ中为我们封装了跨域的方法,有两种方式:

1.$.ajax()方法
<script type="text/javascript">
  $(function(){
    $.ajax({                
      url:"http://api.map.baidu.com/telematics/v3/weather?location=北京                                        &output=json&ak=tq0Kt0NFYheTCj5mszast0drkIqqVTNn",                
      dataType:"jsonp",//只需要将dataType设置为jsonp即可
      success:function(data){                    
        console.log(data)
      }
    })
  })
</script>
需要注意的是,src这个属性实际上是等同于发送了一个GET形式的Ajax请求,包括href,所以我们在页面中尽量不要写空的href和src属性,可以减小服务器的压力

jsonp实际上就是我们手动创建script,然后再script中引用某一个js文件
2.getJson方式
<script type="text/javascript">
  $.getJson('http://csdn.net/blog/data.java?callback=?',function(data){console.log(data)//处理返回的数据});
</script>
window.name

在一个window的存活周期下,窗口载入的所有页面都共享一个window.name属性,每个页面都对它有可读可写的权限,即使window.location重载也不会有变化

window.name的格式为字符串,更多的时候我们使用json的格式来进行书写,window.name存在字符串的限制,最大的大小为2M

下面我们来举一个栗子:

a.html

  <body>
    <input type="button" id="btn" value="点击">
    <script>
        window.name="这是a网页设置的";
        document.getElementById("btn").onclick=function(){
            window.location.href="b.html"
        }
    </script>
  </body>

b.html

  <body>
    <script>
        console.log(window.name);//"这是a网页设置的"
    </script>
  </body>

双向数据请求

window.postMessage

这个方法和window.name一样,需要是同一个页面打开的窗口

我们直接来举一个栗子:

//数据端发送
<script>
//弹出一个新窗口
var myPopup = window.open(domain 
            + '/windowPostMessageListener.html','myWindow');

//周期性的发送消息
setInterval(function(){
    var message = 'Hello!  The time is: ' + (new Date().getTime());
    var domain = 'http://scriptandstyle.com';
    console.log('blog.local:  sending message:  ' + message);
    myPopup.postMessage(message,domain);
  //postMessage有两个参数1.message代表的是要发送的数据
                     // 2.domain代表的是要发送数据到哪个地址
},6000);
</script>
//数据端接收
<script>
  //响应事件
window.addEventListener('message',function(event) {
    if(event.origin !== 'http://davidwalsh.name') return;
    console.log('message received:  ' + event.data,event);
    event.source.postMessage('holla back youngin!',event.origin);
},false);
  //需要注意的是1.需要对浏览器进行判断,众所周知IE使用的是attachEvent
  //这里注意message是postMessage的接收事件,其中有三个参数1.source,代表消息源,也就是发送消息的窗口
                                                    //2.origin,代表消息源的url,包含协议,端口,域名,用来验                                                    证数据源
                                                    //3.data,发送方发送过来的数据
</script>
后台转换

这个方法是实际工作中最常用的,我们如果有需要跨域请求数据,一般会让后台配合请求到数据然后在返回给前台使用

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 162,050评论 4 370
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,538评论 1 306
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 111,673评论 0 254
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,622评论 0 218
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 53,047评论 3 295
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,974评论 1 224
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,129评论 2 317
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,893评论 0 209
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,654评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,828评论 2 254
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,297评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,619评论 3 262
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,326评论 3 243
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,176评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,975评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,118评论 2 285
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,909评论 2 278

推荐阅读更多精彩内容