讲到跨域通信,我们首先要了解什么是跨域?跨域大致的意思就是,比如:www.XXX.com域名下的js是不能操作www.YYY.com域名下的对象或者元素。了解了跨域的大概意思之后,接下来为了能够在本地演示跨域的操作,我们首先要在本地的电脑上搭建虚拟服务器环境。我的电脑上用的是PHPnow(PHPnow是一个集成Apache+PHP+MySQL环境套件包).具体操作如下:
①安装PHPnow(安装比较简单就不介绍了)
②打开PHPnow的安装页面,运行PnCp文件。
③选择编号执行相应的操作(标号0)
④添加主机(我之前已经添加了两个)
⑤本地域名映射,打开hosts文件:路径C:\Windows\System32\drivers\etc,添加本地映射
⑤在hosts中添加之前你写的域名。
⑥打开浏览器输入你写的域名,虚拟服务器搭建完毕。
同域文档之间的访问方式,在ajax这一栏目下我会在博客中列出。目前先说几个:iframe,window.open,ajax等。那同域文档之间的通信,js是否可以随便操作同域文档所在的窗口对象呢?答案请看示例。
1.iframe内嵌同域名文档。
下面是1iframe.html文档:
window.onload = function(){
var oInput = document.getElementById('in1');
var oMyIfram = document.getElementById('iframe');
oInput.onclick = function(){
//如果我们要操作一个iframe里面的dom元素,首先要获取到iframe引入的页面的window
oMyIfram.contentWindow.document.body.style.background = '#c0c0c0';
};
};
我是www.chenming.com底下的1.iframe.com的内容
window.onload = function(){
var oIn = document.getElementById('in');
oIn.onclick = function(){
//window parent top
parent.document.body.style.background = 'green';
};
};
说明:1iframe.html中通过iframe内嵌了同域名底下的文档1.iframe.html,也就是在1iframe.html的页面中嵌入了另一个窗口,那么1iframe.html中想操作1.iframe.html所在窗口,首先获取iframe对象oMyIframe,接着调用contentWindow
oMyIfram.contentWindow//获取到1.iframe.html所在窗口对象。
那么1.iframe.html所在页面也可以操作1iframe.html页面。
1.iframe.html页面他有自身的window页面,父级页面parent,顶级页面top,层级是Window<=parent<=top;
那我们调用parent这个窗口对象就可以操作1iframe.html页面页面了。
2.window.open打开同域名文档。
下面是1window.html文档:
window.onload = function(){
var aInput = document.getElementsByTagName('input');
var newWindow = null;
aInput[0].onclick = function(){
//window.open 返回被打开窗口的window对象
newWindow = window.open('1.window.html','_blank');
};
aInput[1].onclick = function(){
newWindow.document.body.style.background = 'green';
};
};
下面是1.window.html文档:
我是www.chenming.com底下的1.window.html的内容
window.onload = function(){
var oInput = document.getElementsByTagName('input')[0];
oInput.onclick = function(){
//window.opener : 通过window.open方法打开当前页面的窗口window
window.opener.document.body.style.background = '#c0c0c0';
};
};
说明:1window.html通过window.open()打开了新的页面1.window.html。这个open打开之后返回一个窗口对象。这个窗口对象就是1.window.html的页面,那我们就可以利用这个对象来操作1.window.html的页面元素了。相反的,如果想要1.window.html的页面操作1window.html,那我们首先要获取到他的窗口对象,可以通过窗口对象下的一个方法来获取:window.opener;3.ajax访问同域名文档。
ajax同域名访问也是没有问题的,因为在我的ajax原理与封装( http://blog.csdn.net/dreamchenming/article/details/52174014 )这一块说过,这里就不再赘述了。
之前我们在ajax栏目的博客中介绍过同域底下文档的通信,那ajax可否进行跨域通信呢?先来看一个ajax是跨域请求的例子:
下面是http://www.chenming.com/ajax.html文档:
window.onload = function(){
var oBtn = document.getElementById('btn');
oBtn.onclick = function(){
/*
在标准浏览器下,XMLHttpRequest对象已经是升级版本,支持了更多的特性,可以跨域了
但是,如果想实现跨域请求,还需要后端的相关配合才可以
XMLHttpRequest : 增加很多功能,他也不推荐使用onreadystatechange这个事件来监听,推荐使用onload
XDomainRequest : IE如果想实现跨域请求,则需要使用另外一个对象去实现
*/
/*var xhr = new XMLHttpRequest();xhr.onreadystatechange = function(){if(xhr.readyState == 4){if(xhr.status == 200){alert(xhr.responseText);}}}xhr.open('get','http://www.chenming1.com/1.php',true);xhr.send();*/var xdr = new XDomainRequest();xdr.onload = function(){alert(this.responseText);};xdr.open('get','http://www.chenming1.com/1.php',true);xdr.send();};};
下面是http://www.chenming1.com/1.php文档:
说明:当我们这样通过ajax跨域访问的时候,浏览器console出现了下面的情况:
上述提示缺少了‘Access-Control-Allow-Origin’这个头信息,那我们是不是就不能通过ajax跨域访问了,当然不是,我们只要让后台文件配合就可以跨域通信了,方式如下:
ajax只要后台配合就可以跨域访问,那我们通过iframe方式能不能跨域请求呢?一试便知,看下面的例子:
下面是www.chenming.com/2iframe.com文档:
window.onload = function(){
var oInput = document.getElementById('in1');
var oMyIfram = document.getElementById('iframe');
oInput.onclick = function(){
//当本页面和包含页面不在同一个域名下的时候,这样操作就会有跨域操作安全限制问题。
//oMyIfram.contentWindow.document.body.style.background = '#c0c0c0';
}
};
下面是www.chenming1.com/2.iframe.com文档:
我是www.chenming1.com底下的2.iframe.com的内容
window.onload = function(){
var oIn = document.getElementById('in');
oIn.onclick = function(){
parent.postMessage('2','http://www.chenming.com/2iframe.html');
};
};
说明:结果我们发现通过iframe跨域通信受限制了,也就是之前操作同域的方式来操作跨域是行不通的。
那我们有没有其他方式来解决跨域通信的问题呢?html5中提供了postMessage的方法可以帮助我们解决这个跨文档通信的问题。一起来看看是怎么用的吧。
下面是www.chenming.com/2iframe.com文档:
window.onload = function(){
var oInput = document.getElementById('in1');
var oMyIfram = document.getElementById('iframe');
oInput.onclick = function(){
//当本页面和包含页面不在同一个域名下的时候,这样操作就会有跨域操作安全限制问题。
//oMyIfram.contentWindow.document.body.style.background = '#c0c0c0';
/*
postMessage : 可以通过这个方法给另外一个窗口发送信息
接收消息的窗口的window对象.postMessage();
*/
oMyIfram.contentWindow.postMessage('1','http://www.chenming1.com/1.iframe.html');
};
window.addEventListener('message',function(ev){
if(ev.data == '2'){
window.document.body.style.background = '#c0c0c0';
}
},false);
};
下面是www.chenming1.com/2.iframe.com文档:
window.onload = function(){
var oIn = document.getElementById('in');
oIn.onclick = function(){
parent.postMessage('2','http://www.chenming.com/2iframe.html');
};
/*
message : 当窗口接收到通过postMessage发送过来的数据的时候触发
*/
window.addEventListener('message',function(ev){
//alert(ev.origin+'发送了'+ev.data);
if(ev.data == '1'){
window.document.body.style.background = 'green';
}
})
};
当然了,postMessage是发送一个数据给另一个页面,另一个页面一直去监听message事件。而不是一个页面直接去操作另一个页面的元素,所以这个方式可以让两个页面进行协调,比如,这个页面传入什么值的时候,另一个页面发生相应的变化即可。除了ajax(后台文件配合加头文件),postMessage等跨域通信解决方式之外,还有没有其他的方式呢?后续我会在ajax栏目的博客中写另一种跨域请求的解决方式:那就是JSONP( JSON WITH PADDING ),这个方式就是通过script标签内嵌跨域页面,然后通过一个回调函数将数据传输给我们,具体的到时候在ajax栏目的博客中去看。
这一块介绍一下ajax是如何解决无刷新上传的,具体的我就直接上代码了,代码里面也有解说。
后台上传php文件
1,'msg'=>'错误提交方式'));
}
if(array_key_exists('file',$_FILES) && $_FILES['file']['error'] == 0 ){
$pic = $_FILES['file'];
if(move_uploaded_file($pic['tmp_name'], $upload_dir.$pic['name'])){
exit_status(array('code'=>0,'msg'=>'上传成功','url'=>$upload_dir.$pic['name']));
}
}
echo $_FILES['file']['error'];
exit_status(array('code'=>1,'msg'=>'出现了一些错误'));
function exit_status($str){
echo json_encode($str);
exit;
}
?>
上传页面:
0%
window.onload = function(){
var oMyFile = document.getElementById('myFile');
var oBtn = document.getElementById('btn');
var oBox = document.getElementById('box');
var oProgress = document.getElementById('progress');
var oScale = document.getElementById('scale');
oBtn.onclick = function(){
//console.log(oMyFile.files[0]);
var xhr = new XMLHttpRequest();
xhr.onload = function(){
console.log('上传成功');
};
xhr.open('post','post_file.php',true);
xhr.setRequestHeader('X-Request-With', 'XMLHttpRequest');
var oFormData = new FormData(); //通过FormData来构建提交数据
oFormData.append('file', oMyFile.files[0]);
xhr.send(oFormData);
var oUpload = xhr.upload;
oUpload.onprogress = function(ev){
var ev = ev || event;
console.log(ev.loaded + ':'+ev.total);
oBox.style.display = 'block';
//ev.total ev.loaded;
var iScale = Math.floor(ev.loaded/ev.total)*100;
oProgress.style.width = iScale*2 + 'px';
oScale.innerHTML = iScale + '%';
};
};
};
效果图: