1. JSONP 是一种跨域问题解决方案,它利用了 script、img、iframe、link 等标签可以跨域的性质,来避免浏览器同源策略对跨域的限制. 不过除了 script ,其他标签均接收不到服务器数据.
2. JSONP 跨域步骤:
【1】JavaScript 实现对 URL 和 查询字符串 的拼接,并加上“callback=回调函数名”
【2】将拼接后的 URL 赋值给 script 标签的 src 属性
【3】定义全局函数 window[funcName] 用于动态回调
【4】script 忽略浏览器同源策略的限制,跨域请求目标资源,服务器收到访问请求后,获取查询字符串,并得到回调函数名
【5】服务器返回的是一段 JavaScript 语法文档,因此动态调用回调函数,若使用 express 框架,即为 res.send(`${callback}('${data}')`),此处 data 为一个变量名,存放着需要返回的数据
<script> function myJsonp(url, params, callback) { /* funcName 防止重名,随机生成 */ let funcName = 'myJson_' + Math.random().toString().substr(2, 5); let arr = []; for (let key in params) { arr.push(`${key}=${params[key]}`) } arr.push(`callback=${funcName}`); // 创建 script 标签,并赋值 script.src const script = document.createElement('script'); script.src = `${url}?${arr.join("&")}`; document.body.appendChild(script); // 在DOM中添加 script 标签,则后面会执行 script 请求服务器 // 在 JavaScript 中定义全局函数 window[funcName] = function (data) { callback(data); document.body.removeChild(script); } } // 使用myJsonp myJsonp("http://localhost:3000/index", {params: "我是coolFish"}, (data) => { console.log(data + ' hello express'); }) </script>
Express 部分:首先安装依赖 npm install express --save-dev,创建index.js文件,写入下面代码,
运行 node index.js
const express = require("express"); const app = express(); app.get("/index", (req, res) => { let { params, callback } = req.query; // 获取查询字符串 console.log(params); // 我是coolFish console.log(callback); // funcName的值:【随机】myJson_05639 /* res.send() 括号里的内容会被当做 JavaScript 语法解析 */ res.send(`${callback}('${params}') console.log('test res.send()'); `); }); app.listen(3000, () => { console.log("服务开启成功了"); //yellow });
结果: