解决Ajax中的跨域请求
一、什么是跨域请求?
Ajax技术由于受到浏览器的限制,该方法不允许跨域通信,如上图所示,主要原因:
同源策略阻止从一个域上加载的脚本获取或操作另一个域上的文档属性。也就是说,受到请求的 URL 的域必须与当前 Web 页面的域相同。这意味着浏览器隔离来自不同源的内容,以防止它们之间的操作。
Ajax为什么不能实现跨域请求?
出于安全性考虑,默认情况下,浏览器中的同源策略不允许我们向另外一个域发送请求。
二、如何解决跨域请求呢?
我们实现跨域的最根本目的,就是获取服务端数据。所以我们可以借助于script标签中的src属性,其是可以跨域的。
http://www.test1.com/test.html
<script> // 定义一个函数,与fn参数后面的值同名 function callback(msg) { alert(msg); } </script> <script src="http://www.test2.com/ajax.php?fn=callback"></script>
http://www.test2.com/ajax.php
// 接受参数fn $fn = $_GET['fn']; // $fn = 'callback' // 定义一个字符串 $str = 'Hello World'; // 输出字符串 echo $fn."('$str')"; // callback('Hello World!');
以上程序虽然实现了跨域问题,但是当页面一载入完毕后,系统就会发送请求获取结果,很不灵活,如何解决这个问题呢?
三、jsonp技术
JSONP是一个非官方的协议,它允许在服务器端集成script tags返回至客户端,通过javascript callback的形式实现跨域访问。
json与jsonp的区别?
json是一种通用的数据传输格式,主要实现数据的传输与存储。
jsonp是一种非官方协议,主要用于解决Ajax跨域请求问题。
http://www.test1.com/test.html
<script> // 定义一个函数,与fn参数后面的值同名 function callback(msg) { alert(msg); } // 原生代码解决跨域问题(jsonp) window.onload = function() { //为btnok按钮绑定相关事件 document.getElementById('btnok').onclick = function() { //1、创建script标签 var script = document.createElement('script'); //script标签 //2、设置script标签的src属性 script.src = 'http://www.test2.com/ajax.php?fn=callback&_='+new Date().getTime(); // 通过时间戳的形式解决缓存问题 //3、追加script标签到当前文档中 document.getElementsByTagName('head')[0].appendChild(script); } } </script> <input type="button" id='btnok' value='获取数据' />
http://www.test2.com/ajax.php
// 接受参数fn $fn = $_GET['fn']; // $fn = 'callback' // 定义一个字符串 $str = 'Hello World'; // 输出字符串 echo $fn."('$str')"; // callback('Hello World!');
这就是我们所谓的jsonp技术。
四、jQuery中的三个方法
在实际项目开发中,虽然可以通过jsonp技术来实现跨域请求,但是过于麻烦,在jQuery中,可以通过如下三个方法来解决跨域请求问题。
- $.ajax
- $.get
- $.getJSON
所有的跨域请求都是基于get方法实现的,jQuery只是在客户端定义了以上三个方法,但是服务器端是没有任何改变的,谨记!!!
1. $.ajax方法实现跨域请求
http://www.test1.com/test.html
<script> //定义ready方法 $(function(){ //为按钮绑定相关事件 $('#btnok').bind('click',function(){ //发送ajax请求 $.ajax({ type:'get', cache:false, url:'http://www.test2.com/ajax.php', dataType:'jsonp', //期待的返回值类型text/xml/json/jsonp jsonp:'fn', //设置请求的参数名 success:function(msg) { $(msg).each(function(i,item){ //生成op对象 var op = new Option(item.goods_name,item.goods_id); $('#category')[0].options.add(op); }); } }); }); }); //定义ready方法 </script> <input type="button" id='btnok' value='获取数据' /> <select id="category"></select>
http://www.test2.com/ajax.php
//链接数据库 mysql_connect('localhost','root',''); mysql_query('use mall'); mysql_query('set names utf8'); //组装sql语句 $sql = "select goods_name,goods_id from mall_goods"; $res = mysql_query($sql); //定义一个数组保留数据 $data = array(); while($row = mysql_fetch_assoc($res)) { $data[] = $row; } //生成json格式的数据 $str = json_encode($data); // 接受参数fn $fn = $_GET['fn']; // 组装成callback();形式 echo $fn."($str)";
2. $.get方法实现跨域请求
http://www.test1.com/test.html
<script> $(function(){ //绑定按钮相关事件 $('#btnok').bind('click',function(){ //发送Ajax请求 var data = { _:new Date().getTime() }; $.get('http://www.test2.com/ajax.php?fn=?',data,function(msg){ $(msg).each(function(i,item){ $('#result').append(item.goods_id+'->'+item.goods_name+'<hr />'); }); },'jsonp'); }); }); </script> <input type="button" id='btnok' value='获取数据' /> <div id="result"></div>
http://www.test2.com/ajax.php 同上
3. $.getJSON方法实现跨域请求
http://www.test1.com/test.html
<script> //定义ready方法 $(function(){ //为按钮绑定相关事件 $('#btnok').bind('click',function(){ //发送ajax跨域请求 var data = { _:new Date().getTime() }; $.getJSON('http://www.test2.com/ajax.php?fn=?',data,function(msg){ $(msg).each(function(i,item) { $('#result').append(item.goods_id+'->'+item.goods_name+'<hr />'); }); }); }); }); </script> <input type="button" id='btnok' value='获取数据' /> <div id="result"></div>
http://www.test2.com/ajax.php 同上