什么是跨域:
这是一个普通的网址:http:// www . google : 8080 /script/jquery.js
http:// (协议号)
www (子域名)
google (主域名)
8080 (端口号)
script/jquery.js (请求的地址)
当一个网页页面访问另一个网页页面时,URL的协议、子域名、主域名、端口号,这几个中有任意一个不相同,则为跨域访问。之所以存在着跨域,是出于安全考虑,ajax只能访问本地的资源。
解决跨域访问的方式有:
1、代理(主要是指后端设置的服务器代理)
通过后台(ASP、PHP、JAVA、ASP.NET)获取其他域名下的内容,然后再把获得内容处理过后返回到前端,对前端来说就相当于在同一个域名下访问,所以
就不会出现跨域的问题。这里主要以JSONP为主,因此后端的技术不在这里展开讲。
2、JSONP(通过动态创建script标签来引入地址)
我们知道,现在网上有许多前端的开源插件或者框架,如果不想自己下载到本地去调用的话,是可以通过<script>标签去引入外部的资源的,比如jquery的引用,可以通过CDN(内容分发网络)引用它。
一个比较真实的例子就是通过微软给的地址去引用jquery:
<script src="http://ajax.htmlnetcdn.com/ajax/jQuery/jquery-1.10.2.min.js"> </script>
既然这个方式可以引用外部资源,那么我们是不是也可以通过动态创建<script>标签来引用外部资源,从而实现跨域请求呢,答案是显而易见的。
下面我们通过<script>引用去读取一个php文件里面的内容看看。
环境状态:wamp的集成开发服务器搭建,我把文件都放在www这个目录下
下面是php文件的内容
<?php
$arr = array('12345','67890','abcde','fghijk','lmnopq');
echo 'fn('.json_encode($arr).')';
?>
下面是html文件的内容
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>跨域请求测试</title>
<script>
window.onload = function(){
var oBtn = document.getElementById('btn');
oBtn.onclick = function(){
var oScript = document.createElement('script');
oScript.src = 'test.php';
document.body.appendChild(oScript);
}
}
function fn(data){
var oUl = document.getElementById('list');
var html = '';
for(var i = 0;i < data.length; i++){
html += '<li>'+data[i]+'</li>';
}
oUl.innerHTML = html;
}
</script>
</head>
<body>
<input type="button" id="btn" value="按钮"/>
<ul id="list"></ul>
</body>
</html>
浏览器在 localhost下输出的结果
可以看到,数据已经读取到。
下面测试一下通过百度的开放接口去实现跨域请求。
html代码如下:
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>百度开放端口实现跨域请求</title>
<style>
#search {width: 300px; height: 30px; padding: 5px; border:1px solid #f90; font-size: 16px;}
#list {border:1px solid #f90; width: 310px; margin: 0;padding: 0; display: none;}
li a { line-height: 30px; padding: 5px; text-decoration: none; color: black; display: block;}
li a:hover{ background: #f90; color: white; }
</style>
<script>
function fn(data) {
var oUl = document.getElementById('list');
var html = '';
if (data.s.length) {
oUl.style.display = 'block';
for (var i=0; i<data.s.length; i++) {
html += '<li><a target="_blank" href="http://www.baidu.com/s?wd='+data.s[i]+'">'+ data.s[i] +'</a></li>';
}
oUl.innerHTML = html;
} else {
oUl.style.display = 'none';
}
}
window.onload = function() {
var oSearch = document.getElementById('search');
var oUl = document.getElementById('list');
oSearch.onkeyup = function() {
if ( this.value != '' ) {
var oScript = document.createElement('script');
oScript.src = 'http://suggestion.baidu.com/su?wd='+this.value+'&cb=fn';
document.body.appendChild(oScript);
} else {
oUl.style.display = 'none';
}
}
}
</script>
</head>
<body>
<input type="text" id="search" />
<ul id="list"></ul>
</body>
</html>
可以从代码中看到,每次按键弹起,创建一个<script>标签去请求信息,返回的信息通过回调函数保存,我们可以处理回调过来的数据,把它显示到页面上去。
下面使用jquery里的ajax()方法来测试一下跨域请求:
引用本地的jquery压缩文件,html代码如下
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>百度搜索</title>
<script type="text/javascript" src="jquery-1.10.1.min.js"></script>
<script>
$(function(){
$('#keyword').keyup(function(){
$.ajax({
type:"get",
url:"https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su",
async:true,
dataType:"jsonp",
jsonp:"cb",
data:{"wd":$('#keyword').val()},
success:function(data){
console.log(data.s);
var html = '';
for(var i=0;i<data.s.length;i++){
html += '<li>'+data.s[i]+'</li>';
}
$('#list').html(html);
}
});
if($('#keyword').val()==''){
for(var i=0;i<$('#list li').size();i++){
$('#list li').remove();
}
}
})
});
</script>
</head>
<body>
百度关键词搜索:<input type="text" id="keyword"/>
<ul id="list">
</ul>
</body>
</html>
在localhost下打开页面测试的显示结果是
以上就是jsonp的跨域请求方式。
3、XHR2(H5里的XMLHttpRequest Level2)
* IE10以下的版本都不支持
* 只需要在服务器端头部加上下面两句代码:
header( "Access-Control-Allow-Origin:*" );
header( "Access-Control-Allow-Methods:POST,GET");
H5的方式不是这里要探讨的内容,因此不在这里展开。