JS跨越问题解决方法

本文介绍了浏览器同源策略的限制及为何需要跨域,并提供了两种跨域方法:通过jsonp跨域及修改window.name跨子域。

一.同源策略的限制

首先,我们需要知道跨域就是在不同的域之间进行数据传输或通信。只要协议域名端口有任何一个不同,都被当作是不同的域。当要想跨域,就得理解浏览器的同源策略限制。
其限制之一就是我们说的不能通过ajax的方法去请求不同源中的文档。 它的第二个限制是浏览器中不同域的框架之间是不能进行js的交互操作的
关于第二个限制,比如,有一个页面,它的地址是http://www.findme.wang/index.html  , 在这个页面里面有一个iframe,它的src是http://manual.findme.wang/search.html, 很显然,这个页面与它里面的iframe框架是不同域的,所以我们是无法通过在页面中书写js代码来获取iframe中的内容。

二.为什么要跨

因为浏览器同源策略限制,我们没法在两个不同的域直接进行数据传输或通信。如以下代码:

<script type="text/javascript" src="jquery.js"></script>
<script>
$.post('https://www.baidu.com',function(text){
	console.log(text);
});
</script>

执行结果如下:


三、怎样实现跨域

1、通过jsonp跨域(针对限制

在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>

在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).')';

结果如下:


原理分析:通过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>


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>

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>

结果如下


从结果可以看出,这个案例证实了浏览器中不同域的框架之间是不能进行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

IE8开始支持,如果你的项目不用兼容IE6,IE7的话使用这种方式最好。

IE6,IE7需要如此访问

var doc = 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的元素
});





在Vue.js项目打包(通常使用Webpack或者其他构建工具)之前处理问题,可以采取以下几种方法: 1. **配置服务器**: 如果你是后端开发者,可以在服务器端设置允许特定来源的请求。例如,在Node.js的Express应用中,可以添加中间件如`cors`: ```javascript const express = require('express'); const cors = require('cors'); app.use(cors({ origin: 'http://your-domain.com', // 更改为你需要的源地址 credentials: true, })); ``` 2. **JSONP**: 对于只支持GET请求并且目标名与当前名相同的简单请求,可以尝试使用JSONP。 3. **代理** (Webpack dev server): 在Webpack的开发环境中,可以使用`proxy`选项来转发非同源请求到指定的服务器。例如,在`.webpack.dev.conf.js`文件中: ```javascript module.exports = { devServer: { proxy: { '/api': { target: 'https://api.example.com', changeOrigin: true, }, }, }, }; ``` 4. **CORS插件**: 使用像`axios`这样的库,你可以配置它在发送异步请求时自动处理CORS。比如: ```javascript axios.defaults.withCredentials = true; axios.interceptors.request.use(config => { if (process.env.NODE_ENV === 'development') { config.headers.common['X-Custom-Header'] = 'some-value'; } return config; }, error => Promise.reject(error)); ``` 5. **预设响应头**: 在服务端,设置Access-Control-Allow-Origin、Access-Control-Allow-Methods等HTTP头部,允许特定的请求。 完成后记得检查浏览器的网络请求头是否包含正确的信息。如果项目已经打包并部署,上述方法就无法直接用了,你需要在生产环境的服务器上配置。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值