首页 > 代码库 > Ajax跨域与解决方案
Ajax跨域与解决方案
1.同步交互与异步交互
同步交互:用户在URL地址输入http://www.baidu.com,服务器接收请求并进行相应处理,此时用户无法操作,只能等待,只有当返回数据到客户端的时候,用户才能继续操作
异步交互:用户操作某个页面,请求某个数据,客户可以继续操作(服务器返回数据),不涉及到整个页面的刷新
2.XmlHttp
XmlHttp是一套可以在Javascript、VbScript、Jscript等脚本语言中通过http协议传送或从接收XML及其他数据的一套API。XmlHttp最大的用处是可以更新网页的部分内容而不需要刷新整个页面
3.ajax demo (理解ajax)
文件有两个1.html和1.php
1.html代码如下
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Document</title> 6 </head> 7 <body> 8 <input type="button" value="ajax" id="ajax" /> 9 <div id="msg"></div> 10 </body> 11 <script> 12 var button = document.getElementById(‘ajax‘); 13 button.onclick = function() { 14 //创建XmlHttp对象 15 var xhr = new XMLHttpRequest(); 16 //创建请求 17 xhr.open(‘post‘,‘1.php‘); 18 //如果需要像HTML表单那样POST数据,请使用 setRequestHeader()来添加HTTP头,如果不添加这一行代码php接受不到post数据 19 xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); 20 //发送请求到http服务器 21 xhr.send(‘username=yaxian&age=18‘); 22 //当XMLHTTPRequest对象的readyState属性改变时的事件处理句柄 23 xhr.onreadystatechange = function() { 24 //返回XMLHTTP请求的当前状态 4代表数据接受完毕 25 if(xhr.readyState == 4) { 26 //返回当前请求的http状态码 200代表OK 27 if(xhr.status == 200) { 28 //将响应信息作为字符串返回 29 var data = xhr.responseText; 30 document.getElementById(‘msg‘).innerHTML = data; 31 } 32 } 33 } 34 } 35 </script> 36 </html>
1.php代码如下
1 <?php 2 echo ‘php data : ‘.$_POST[‘username‘].$_POST[‘age‘]; 3 ?>
结果是:
4.Ajax跨域是什么
我们先回顾一下域名地址的组成:
http:// www . google : 8080 / script/jquery.js
http:// (协议号)
www (子域名)
google (主域名)
8080 (端口号)
script/jquery.js (请求的地址)
* 当协议、子域名、主域名、端口号中任意一各不相同时,都算不同的“域”。
* 不同的域之间相互请求资源,就叫“跨域”。
比如:http://www.abc.com/index.html 请求 http://www.def.com/sever.php
由于在工作中需要使用AJAX请求其他域名下的请求,但是会出现拒绝访问的情况,这是因为基于安全的考虑,AJAX只能访问本地的资源,而不能跨域访问。比如说你的网站域名是aaa.com,想要通过AJAX请求bbb.com域名中的内容,浏览器就会认为是不安全的,所以拒绝访问
5.解决方案
方案1 jsonp
JSONP是JSON格式的扩展.如果指定了script或者jsonp类型,那么当从服务器接收到数据时,实际上是用了<script>标签而不是XMLHttpRequest对象。这种情况下,$.ajax()不再返回一个XMLHttpRequest对象,并且也不会传递事件处理函数,比如beforeSend。
jsonp有什么用:由于同源策略的限制,XmlHttpRequest只允许请求当前源(域名、协议、端口)的资源,为了实现跨域请求,可以通过script标签实现跨域请求,然后在服务端输出JSON数据并执行回调函数,从而解决了跨域的数据请求
html代码如下(使用jquery):
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Document</title> 6 <script type="text/javascript" src="jquery.js"></script> 7 </head> 8 <body> 9 <input type="text" id="telephone" /> 10 <button id="ajax">提交</button> 11 </body> 12 <script> 13 $(function() { 14 var ajax = $(‘#ajax‘); 15 //$.ajax是jquery封装方法,底层还是使用XMLHttpRequest发送请求,还是有跨域限制 16 ajax.click(function() { 17 var telephone = $(‘#telephone‘).val(); 18 19 $.ajax({ 20 type : ‘get‘, 21 url : ‘http://api.jisuapi.com/shouji/query‘, 22 data : ‘appkey=yourappkey&shouji=‘+telephone, 23 dataType : ‘jsonp‘, 24 success:function(msg){ 25 console.log(msg); 26 } 27 }); 28 }); 29 }); 30 </script> 31 </html>
结果:
若注释dataType:‘jsonp‘这一行代码结果如下:(提示跨域导致请求失败)
html代码如下(原生js,不使用jquery)
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Document</title> 6 </head> 7 <body> 8 <button id="ajax">通过script标签发送请求</button> 9 </body> 10 <script> 11 /* 12 因为服务器返回的数据格式是{"username":"yaxian", "age":18},客户端以js语法无法解析 13 所以客户端需要给服务器传递一个回调函数,服务器返回一个回调函数的调用,并将服务端数据包含在这个函数调用里面 14 这样客户端得到的是这样的数据getInfo({"username":"yaxian", "age":18}),js解析后会调用getInfo函数 15 这种方式只能解决get方式跨域,因为script标签发送请求是get请求 16 */ 17 var ajax = document.getElementById(‘ajax‘); 18 function getInfo(obj) { 19 console.log(obj); 20 } 21 ajax.onclick = function() { 22 var script = document.createElement(‘script‘); 23 //callback是跨域通用的参数名称 24 script.src = ‘http://test.com/1.php?callback=getInfo‘; 25 document.body.appendChild(script); 26 } 27 </script> 28 </html>
php代码如下
1 <?php 2 //接受callback(必须是get方式) 3 $callback = $_GET[‘callback‘]; 4 //getInfo({"username":"yaxian", "age":18}); 5 echo $callback.‘({"username":"yaxian", "age":18})‘; 6 ?>
结果:
方案2 jsonp是get形式,承载的信息量有限,所以信息量较大时CORS是不二选择
6.实例(跨域请求360搜索接口)
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Document</title> 6 <style> 7 .msg{ 8 border:1px solid #ccc; 9 margin-left:-53px; 10 border-top:none; 11 display:none; 12 } 13 ul{ 14 margin:0; 15 padding:0; 16 list-style:none; 17 } 18 .w500{ 19 width:500px; 20 } 21 li{ 22 padding:5px; 23 cursor:pointer; 24 } 25 </style> 26 <script src="jquery.js"></script> 27 </head> 28 <body> 29 <div align="center"> 30 <input type="text" class="keywords w500" id="keywords" /> 31 <input type="button" value="搜索" /> 32 <div class="msg w500" align="left" id="msg"> 33 <ul id="list"> 34 <!-- 35 <li>中国好声音</li> 36 <li>中国666</li> 37 <li>中国王胜涛</li> 38 --> 39 </ul> 40 </div> 41 </div> 42 </body> 43 <script> 44 function getInfo(obj) { 45 //如果直接给li绑定事件获取不到li元素,使用jquery事件委托 46 $(‘#msg‘).on(‘mouseover‘, ‘li‘, function() { 47 this.style.background = "#ccc"; 48 }); 49 $(‘#msg‘).on(‘mouseout‘, ‘li‘, function() { 50 this.style.background = ""; 51 }); 52 53 //解析数据 54 var result = obj.result; 55 document.getElementById(‘list‘).innerHTML = ‘‘; 56 for(var i = 0; i < result.length; i++) { 57 var li = document.createElement(‘li‘); 58 li.innerHTML = result[i].word; 59 document.getElementById(‘list‘).appendChild(li); 60 } 61 } 62 document.getElementById(‘keywords‘).onkeyup = function() { 63 var keywords = this.value; 64 if(keywords.length>0) { 65 //显示提示区域 66 document.getElementById(‘msg‘).style.display = ‘block‘; 67 //使用script标签发送请求 68 var script = document.createElement(‘script‘); 69 script.src = ‘https://sug.so.360.cn/suggest?callback=getInfo&encodein=utf-8&encodeout=utf-8&format=json&fields=word,obdata&word=‘+keywords; 70 document.body.appendChild(script); 71 } else { 72 //隐藏提示区域 73 document.getElementById(‘msg‘).style.display = ‘none‘; 74 } 75 } 76 </script> 77 78 </html>
结果:
Ajax跨域与解决方案