跨域请求
什么是跨域请求
浏览器为了安全性问题,做出了同源策略的限制,跨域请求是不能请求的。什么是域:域就是协议名和主机名+端口号。只有三部分都一样才能说是相同的域。相同域之间不受限制,不同域之间不能相互请求。
如何处理跨域请求
jsonp处理跨域请求,跨域请求很多常见的是jsonp。
平时用的<img>,<link>,<script>这些标签是不受跨域限制的。但是能不能让<script>去请求数据来请求获取json数据呢?答案是肯定的。json可以描述复杂的数据。更重要的是json格式的数据能被JavaScript原生支持。于是服务器端就可以生成json文件。这样一种解决跨域请求的方案就出来了,大家称之为jsonp。
请看一下代码
// 服务器
// jsonp跨域
app.get('/3-6-2-json-1.js',function(req,res){
res.render('3-4-1-post');
});
//3-6-2-json-1.js
alert('the message from server');
//jsonp.html
<!DOCTYPE html>
<html>
<head>
<title>jsonp</title>
<meta charset="utf-8">
</head>
<body>
<script type="text/javascript" src="http://localhost:3000/3-6-2-json-1.js"></script>
</body>
</html>
接下来扩展一下
// jsonp1.html
<!DOCTYPE html>
<html>
<head>
<title>jsonp</title>
<meta charset="utf-8">
</head>
<body>
<script type="text/javascript">
function getData(data){
alert("我是本地函數,跨域請求服務器的js文件,服務器返回是:"+data.result);
}
</script>
<script type="text/javascript" src="http://localhost:3000/3-6-2-json-1.js"></script>
</body>
</html>
// 3-6-2-json-1.js
getData({result:'this message from server'});
这样跨域就可以使用了,但是有一个问题就是如何让服务器知道本地的函数名?可以在url后传递参数
封装jsonp
function getData(data){
alert("我是本地函數,跨域請求服務器的js文件,服務器返回是:"+data.result);
}
// 封装jsonp url 请求的url callback回调
ajax.jsonp = function(){
// 创建动态的script标签
var script = document.createElement('script');
// 生成函数名
var time = new Date();
var funcName = 'jsonp' + time.getTime();
}
// 拼接url,判断url中是否有参数
if(url.indexOf('?')>0){
url = url + '&callback=' + funcName;
}else{
url = url + '?callback=' + funcName;
}
// 注册回电函数到全局
window[funcName] = function(data){
callback(data);
delete window[funcName];
script.parentNode.removeChild(script);
}
// 设置script标签的src属性
script.setAttribute('src',url);
// 把script 标签加入到head,请求服务得到数据
document.getElementsByTageName('head')[0].appendChild(script);
}
//调用代码
Ajax().jsonp('http://localhost:3000/3-6-2.js?city=tj&date=20200101',function(data){
function(data){
alert(data.city+'在'+data.date+'天气'+data.weater);
}
})
基于标签
window.name属性始终存在于当前窗口所打开过的所有页面中,不会因页面的刷新和新页面的载入而重置。
// window.name.html
<!DOCTYPE html>
<html>
<head>
<title>window.name</title>
<meta charset="utf-8">
</head>
<body>
<a href="./3-6-2-iframe-2.html">点击在本窗口打开并且查看window.name的值</a>
<script type="text/javascript">
window.name = '这是第一个页面设置的name属性的值'
</script>
</body>
</html>
// 3-6-2-iframe-2.html
<!DOCTYPE html>
<html>
<head>
<title>3-6-2-iframe-2.html</title>
<meta charset="utf-8">
</head>
<body>
<h3>这是在本窗口贷款的第二个嗯,在这个页面显示window.name的值</h3>
<script type="text/javascript">
alert(window.name);
</script>
</body>
</html>
//windowName.html
<!DOCTYPE html>
<html>
<head>
<title>windowName</title>
<meta charset="utf-8">
</head>
<body>
<button onclick="getData()">点击发起跨域请求</button>
<iframe id="iframe" src="http://localhost:3000/3-6-2-iframe-data?name=ab" style="display: none"></iframe>
<script type="text/javascript">
function getData(){
// 获取iframe标签对象
var iframe = document.getElementById('iframe');
iframe.src = 'about:black';
iframe.onload = function(){
var data = iframe.contentWindow.name;
data = JSON.parse(data);
alert(data.name + '的口号是:' + data.info);
}
}
</script>
</body>
</html>
// 服务器
//windowName
app.get('/3-6-2-iframe-data',function(req,res){
var param = req.query.name;
var data = {name:param,info:'唯我独尊'};
var data = JSON.stringify(data);
res.send("<script>window.name='"+data+"';</script>");
});
封装window.name跨域请求
// 封装window.name 跨域请求
ajax.iframe = function(url,callback){
// 创建iframe标签
var iframe = document.createElement('iframe');
// 设置属性为隐蔽
iframe.style = 'none';
// 指定iframe的src属性
iframe.src = url;
// 把iframe写入到body中
document.getElementsByTageName('body')[0].appendChild(iframe);
// 设置标志用于判断,保证src只设定一次
var flag = true;
// src只改变一次,iframe重新加载一次
ajax.onload = function(){
// 判断状态,防止重置src
if(flag){
// 将域设置成同城
iframe.src = 'about:black';
// 一旦设置好后就可以获取window.name的值了
flag = false;
}else{
// 获取服务器设定name
var data = iframe.contentWindow.name;
// 判断用户想要接收的数据类型
if(ajax.dataType == 'JSON'){
// 将json格式字符串转化为json对象
data = JSON.parse(data);
}
// 将数据给回调函数
callback(data);
// 销毁节点
document.body.removeChild(iframe);
}
}
};
// 考虑到兼容
if(iframe.attachEvent){
iframe.attachEvent('onload',ajax.onload);
}else{
iframe.onload = ajax.onload;
}