这是我参与2022首次更文挑战的第10天,活动详情查看:2022首次更文挑战
前言
今天我们来讲一讲跨域的问题,我们常见的跨域方法有jsonp,cors,还有使用一些中间件进行跨域,这篇文章主要讲jsonp跨域的方法,以及jsonP封装,让我们一起来看看吧。
JSONP
jsonp就是利用web页面调用js文件(一般拥有src属性的标签可以跨域的特点,例如script,img,iframe等)进行跨域,服务器端动态生成数据,一般为json格式的文件。客户端利用如script标签对JSON文件调用成功之后,也就获得了自己所需的数据,然后就按照自己需求进行处理和展现了。
JSONP封装
下面我们对json进行封装:
1.jsonp概念与封装注意点:
代价:需要前后端联动 精髓:自动的由插件生成方法名,并在当前的页面动态的生成函数 然后再生成的函数里头调用用户预留的回调函数 插件:自动化的去模拟基于script去实现跨域请求的过程(对用户来说是黑盒子) 参数拼接:url已经是带参的。和不带参的 id优化 额可以添加一个容器来管理id
2.自己封装的jsonp
2.1)js代码(加注释讲解)
<script>
/**
* 1.声明一个jsonP插件对象
* 作用:隔开作用域
*/
let jsonP = {};
/**
*2.在插件对象中创建两个名字备用符数组
*/
jsonP.char = {
Number: '0123456789',
Letter: 'qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM'
}
/**
* 通过随机数抽取备用字符数组库拼凑函数id
* @param charLen
* @param numLen
*/
jsonP.newFunId = function (charLen, numLen) {
let id = '';
for (let i = 0; i < charLen; i++) {
id += this.char.Letter.charAt(Math.random() * 52)
}
for (let j = 0; j < numLen; j++) {
id += Math.floor(Math.random() * 10);
}
return id;
}
/**
* 拼接路径
* @param url
* @param key
* @param value
*/
jsonP.jointUrl = function (url, key, value) {
if (url && key && value) {
let sign = "&"
//如果是第一次
if (url.indexOf('?') == -1) {
sign = '?'
}
url += sign + key + "=" + value
}
return url;
}
/**
封装err属性方便
*/
jsonP.err = function (msg) {
console.error(msg)
}
/**
* 发送请求函数
* @param options
*/
jsonP.req = function (options) {
let jsonId={};
//1.生成方法名
jsonId.funId = this.newFunId(4,8);
let Userurl = options.url;
let Userdata = options.data;
if (!options) {
this.err("输入不能空")
return;
} else if (!Userurl) {
this.err("url不能空")
return;
} else if (!Userdata) {
//如果没有data,初始化
Userdata = {};
}
//将函数名赋值给userdata的回调函数属性中
Userdata.callback = jsonId.funId;
for (let key in Userdata) {
Userurl = this.jointUrl(Userurl, key, Userdata[key])
}
let script = document.createElement('script');
script.setAttribute("id" , jsonId.funId);
script.setAttribute("src" , Userurl);
//动态生成函数
let callback=function (result) {
console.log("xxxxxxx")
//业务逻辑回调
if (options.callback){
try {
options.callback(result)
}catch (e) {
this.err(e.message)
}
}
//善后
let tmp=document.getElementById(jsonId.funId)
tmp.parentNode.removeChild(tmp);
eval(jsonId.funId+'=null')
}
eval("window."+jsonId.funId+"=function(result){ callback(result) }")
document.head.appendChild(script)
}
//测试调用函数
let test=function () {
jsonP.req({
url:"http://localhost:3000/jsonpx",
data:{
a:"111"
},
callback:function (result) {
alert("成功"+result)
}
})
}
</script>
2.2)服务端测试代码
router.get('/jsonpx', async function (req, resp, next) {
let callback=req.query.callback;
let data=req.query.a;
if (!data){
resp.send(`${callback}('洪吉林:我是服务端代码')`)
}
resp.send(`${callback}('洪吉林:我是服务端代码`+data+`')`)
})
总结:这就是使用jsonp进行跨域的方法,封装方面可能还可以做的更简便一些,这就需要各位掘友的思维了,我就讲到这里,下一章我们讲cors进行跨域吧。