JS跨越问题解决方法
转载地址:https://blog.****.net/hsd2012/article/details/52647873
一.同源策略的限制
二.为什么要跨域
因为浏览器同源策略限制,我们没法在两个不同的域直接进行数据传输或通信。如以下代码:
- <script type="text/javascript" src="jquery.js"></script>
- <script>
- $.post('https://www.baidu.com',function(text){
- console.log(text);
- });
- </script>
- <script type="text/javascript" src="jquery.js"></script>
- <script>
- $.post('https://www.baidu.com',function(text){
- console.log(text);
- });
- </script>
执行结果如下:
三、怎样实现跨域
在js中,虽然我们不可以直接用XMLHttpRequest请求不同域上的数据,但是,在页面上引入不同域上的js脚本文件却是可以的,jsonp正是利用这个特性来实现的。
比如,某域下有个index.html页面,它里面的代码需要利用ajax获取一个不同域上(如http://www.findme.wang)的json数据
实现方式如下
index.html内容如下:
- <script>
- //回调函数
- function show(oJson){
- //dosomething
- console.log(oJson['str']);
- }
- </script>
- <script type="text/javascript" src="http://www.findme.wang/test.php?callback=show&name=dqs"></script>
- <script>
- //回调函数
- function show(oJson){
- //dosomething
- console.log(oJson['str']);
- }
- </script>
- <script type="text/javascript" src="http://www.findme.wang/test.php?callback=show&name=dqs"></script>
在http://www.findme.wang域上,要有一个test.php文件,返回一个js文件,并在该文件中,调用回调方法show,内容如下
- $callback=$_GET['callback'];
- $name=$_GET['name'];
- $data=array('str'=>'hello,'.$name);
- echo $callback.'('.json_encode($data,JSON_UNESCAPED_UNICODE).')';
- $callback=$_GET['callback'];
- $name=$_GET['name'];
- $data=array('str'=>'hello,'.$name);
- echo $callback.'('.json_encode($data,JSON_UNESCAPED_UNICODE).')';
结果如下:
原理分析:通过script标签引入一个js文件,这个js文件载入成功后会执行我们在url参数中指定的函数,并且会把我们需要的json数据作为参数传入。当然jsonp是需要服务器端的页面进行相应的配合的。
2、通过修改window.name来跨子域(针对限制二)
为了更加现实效果,我在本地http://localhost/下的index.html文件通过iframe引入了http://www.findme.wang/test.php和http://localhost/test.php,通过JS获取iframe文件中的内容。
index.html文件
- <script type="text/javascript" src="jquery.js"></script>
- <iframe src="http://www.findme.wang/test.php" id="test_box1"></iframe>
- <iframe src="http://localhost/test.php" id="test_box2"></iframe>
- <script type="text/javascript">
- $(function(){
- //针对不同的域名
- $('#test_box1').load(function(){
- //我们能获取到window对象,但是没法获取window对象的属性和方法
- var oiframe1=$("#test_box1");
- var doc1=oiframe1.contents();
- console.log(doc1);
- var div1=doc1.find("#div1");
- console.log(div1.html());
- })
- //针对相同的域名
- $('#test_box2').load(function(){
- var oiframe2=$("#test_box2");
- var doc2=oiframe2.contents();
- console.log(doc2);
- var div2=doc2.find("#div2");
- console.log(div2.html());
- });
- });
- </script>
- <script type="text/javascript" src="jquery.js"></script>
- <iframe src="http://www.findme.wang/test.php" id="test_box1"></iframe>
- <iframe src="http://localhost/test.php" id="test_box2"></iframe>
- <script type="text/javascript">
- $(function(){
- //针对不同的域名
- $('#test_box1').load(function(){
- //我们能获取到window对象,但是没法获取window对象的属性和方法
- var oiframe1=$("#test_box1");
- var doc1=oiframe1.contents();
- console.log(doc1);
- var div1=doc1.find("#div1");
- console.log(div1.html());
- })
- //针对相同的域名
- $('#test_box2').load(function(){
- var oiframe2=$("#test_box2");
- var doc2=oiframe2.contents();
- console.log(doc2);
- var div2=doc2.find("#div2");
- console.log(div2.html());
- });
- });
- </script>
http://www.findme.wang/test.php文件如下
- <html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <title>测试</title>
- </head>
- <body>
- <div id="div1">
- 域名:www.findme.wang;你好啊!!!
- </div>
- </body>
- </html>
- <html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <title>测试</title>
- </head>
- <body>
- <div id="div1">
- 域名:www.findme.wang;你好啊!!!
- </div>
- </body>
- </html>
http://localhost/test.php文件如下
- <html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <title>测试</title>
- </head>
- <body>
- <div id="div2">
- 域名:localhost;你好啊!!!
- </div>
- </body>
- </html>
- <html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <title>测试</title>
- </head>
- <body>
- <div id="div2">
- 域名:localhost;你好啊!!!
- </div>
- </body>
- </html>
结果如下
从结果可以看出,这个案例证实了浏览器中不同域的框架之间是不能进行js的交互操作的。怎样实现他们的交互操作呢?使用HTML5中新引进的window.postMessage方法来跨域传送数据。window.postMessage(message,targetOrigin) 方法是html5新引进的特性,可以使用它来向其它的window对象发送消息,无论这个window对象是属于同源或不同源,目前IE8+、FireFox、Chrome、Opera等浏览器都已经支持window.postMessage方法。
补充
1.如何获取iframe的document对象
W3C的标准告诉我们,可以通过Dom对象的contentDocument属性来返回文档对象。
- var doc = document.getElementById('mainFrame' ).contentDocument
- var doc = document.getElementById('mainFrame' ).contentDocument
IE8开始支持,如果你的项目不用兼容IE6,IE7的话使用这种方式最好。
IE6,IE7需要如此访问
- var doc = document.frames['mainFrame'].document;
- var doc = document.frames['mainFrame'].document;
兼容方式:
- var doc = document.getElementById('mainFrame' ).contentDocument || document.frames['mainFrame'].document;
- var doc = document.getElementById('mainFrame' ).contentDocument || document.frames['mainFrame'].document;
以上是Javascript原生方法:
使用Jquery则简单些
- $('#frameID').load(function () {
- $('#frameID').contents().find('#div1');//在frame中找id为div1的元素
- });
- $('#frameID').load(function () {
- $('#frameID').contents().find('#div1');//在frame中找id为div1的元素
- });