前端Jsonp跨域详解
跨域常见的实现方式:jsonp,hash,websocket,cors,postmessage等。
有时间博主会再单独每部分实现写一篇文章哈哈,废话不多说,进入主题讲讲今天的主角Jsonp跨域。
原理:script img link 获取资源不受浏览器同源策略限制;
废话不多说直接讲代码实现
首先创建一个$jsonp函数封装一个请求方法,接受一个请求链接和一个回调,创建一个script标签,script标签src属性为所要请求的地址,注意相关script通过get方法请求数使用url编码,在script成功加载后去除这个标签(当然你可以留着)。
function $jsonp(url, callback) {
let requestUrl = url + "?callback=" + callback;
let script = document.createElement("script");
script.type = "text/javascript";
script.src = requestUrl;
document.querySelector("body").appendChild(script);
script.onload = function() {
document.querySelector("body").removeChild(script);
};
}
服务器端代码(koa起的服务,服务器需配合前端代码)
app.use(
route.get("/jsonp", async ctx => {
let fn = ctx.request.query.callback;
let data = {
name: "小明"
};
ctx.response.body = fn + "(" + JSON.stringify(data) + ")";
})
);
简单解释下这段代码及增加了一个jsonp(任意名字)接口,正确接受数据后把data 配合callback函数返回回去)
Html
<button class="bth1">Jsonp请求</button>
document.querySelector('.bth1').addEventListener('click', function () {
let url = "http://www.xianliangspace.cn/jsonp";
$jsonp(url, 'getInfo');
})
function getInfo(data) {
console.log("返回数据", data);
}
测试效果
![](https://i-blog.csdnimg.cn/blog_migrate/588f4b7184c9c0ea0a6700a32fbcb58b.png)
基于Img link 实现的原理与script标签相同,就直接上代码了,注意img,link只能实现单项通信即客户端向服务器端发送数据,这是为什么呢?
当然是因为script请求回来的数据作为Javascript 脚本文件运行,img 获取的作为图片加载,link 获取作为样式表文件加载;
注意:img标签跨域实现(注意img在图片加载失败时去除便签,监听onerror事件);
代码实现如下:
function $sendInfoImg(url, data) {
let img = document.createElement("img");
img.src = url + "?name=" + data;
document.querySelector("body").appendChild(img);
img.onerror = function() {
document.querySelector("body").removeChild(img);
};
}
通过创建Image对象实现(广泛用于错误收集)
var img=new Image();
img.src='https://www.xianliangspace.cn/errorCaptured';
后台相关代码
app.use(
route.get("/info", async ctx => {
let name = ctx.request.query.name;
console.log(name);
})
);
测试结果
![](https://i-blog.csdnimg.cn/blog_migrate/0381143d7a000b30f206b7c6306049a6.png)
link 标签实现,同理监听onerror 事件去除标签
function $sendInfoLink(url, data) {
let link = document.createElement("link");
link.type = "text/css";
link.rel = "stylesheet";
link.href = url + "?name=" + data;
document.querySelector("head").appendChild(link);
link.onerror = function() {
document.querySelector("head").removeChild(link);
};
}
后台相关代码通img实现部分
测试结果
![](https://i-blog.csdnimg.cn/blog_migrate/59bdbe87f040aae93e84f8b6b6fa87d7.png)