关于跨域的技巧可以分为 iframe 跨域和 API 跨域。

JSONP 跨域

JSONP 全称:JSON with padding,可用于解决老版本浏览器的跨域数据访问问题。

由于 web 页面上请求的 js 文件不受同源策略的限制,所以可以用 script 标签进行跨域请求:

  1. 首先前端需要事先设置好回调函数,并作为 script 标签 src 属性的查询参数。

  2. 服务端接收到请求后,通过查询参数获取对调函数,并把数据作为回调函数的参数然后将其返回。

  3. 收到结果后因为是 script 标签,所以浏览器会当做脚本自动执行,从而达到跨域获取数据的目的。

jsonp 之所以能够跨域,关键在于页面调用 js 脚本是不受同源策略的影响,相当于向后端发起一条 http 请求,跟后端约定好函数名,后端拿到函数名,动态计算出返回结果并返回给前端执行 JS 脚本,相当于是一种 “动态 JS 脚本”。

  1. // data.js 路由代码
  2. const data = {
  3. state: "success",
  4. data: "test"
  5. };
  6. const callback = query.callback;
  7. response.statusCode = 200;
  8. response.setHeader("Content-Type", "application/javascript");
  9. response.end(`${callback}(${JSON.stringify(data)})`);
  1. // 前端代码
  2. let callbackName = "jsonp" + parseInt(Math.random() * 1000000, 10);
  3. window[callbackName] = function (result) {
  4. console.log(result);
  5. };
  6. let script = document.createElement("script");
  7. script.src = "http://localhost:8081/data.js?callback=" + callbackName;
  8. document.body.appendChild(script);
  9. script.onload = (e) => {
  10. e.currentTarget.remove();
  11. delete window[callbackName];
  12. };
  13. script.error = () => {
  14. console.log("请求失败");
  15. delete window[callbackName];
  16. };

优点

  1. 它不像 XMLHttpRequest 对象实现的 Ajax 请求那样受到同源策略的限制。
  2. 兼容性很好,在一些古老的浏览器上也能很好的运行。

缺点

  1. 因为是 script 标签发请求,所以只支持 GET 请求。

CORS

CORS 是一个 W3C 的标准,全场是 “跨域资源共享”(Cross-origin resource sharing)它允许浏览器向跨源服务器发起 XMLHttpRequest 请求,从而克服了 ajax 只能同源使用的限制。

CORS 需要浏览器和服务器同时支持才可以生效,对于开发者来说,CORS 通信与同源的 ajax 通信吗,没有区别,代码是完全一样。浏览器一旦发现 ajax 请求资源,就会自动添加一些附加头信息,有时还会多出一次附加的请求,但用户不会有感觉。

因此,实现 CORS 通信的关键是服务器。只要服务器实现了 CORS 接口,就可以跨域通信了。

  1. // data.js 路由代码
  2. response.statusCode = 200;
  3. response.setHeader("Content-Type", "text/html;charset=urf-8");
  4. response.setHeader("Access-Control-Allow-Origin", "http://localhost:8080");
  5. response.end("response data");
  1. // 前端逻辑
  2. const xhr = new XMLHttpRequest();
  3. xhr.open("GET", "http://localhost:8081/data.js", true);
  4. xhr.onreadystatechange = () => {
  5. if (xhr.readyState === 4 && xhr.status === 200) {
  6. console.log(xhr.responseText);
  7. }
  8. };
  9. xhr.send();

关键在于设置了响应头 Access-Control-Allow-Origin,该值要与请求头中 Origin 一致才能生效,否则将跨域失败。

CORS 的优缺点

  1. 使用方便,更为安全。
  2. 支持 POST 请求。
  3. CORS 是一种新型的跨域解决方案,存在兼容性问题。

服务端代理

服务端代理,顾名思义,当你需要有跨域的请求操作时发送请求给后端让后端帮你代发请求,然后将获取的结果发送给你。

以请求 CNode 社区 社区的 api 为例。

  1. // 后端逻辑
  2. if (path === "/a.html") {
  3. https.get("https://cnodejs.org/api/v1/topics", (res) => {
  4. let data = [];
  5. res.on("data", chunk => {
  6. data.push(chunk);
  7. });
  8. res.on("end", () => {
  9. response.setHeader("Content-Type", "application/json; charset=utf-8");
  10. response.end(Buffer.concat(data).toString());
  11. });
  12. });
  13. }

通过代码可以看出,当访问 http://localhost:8080/a.html 的时候,服务器收到请求,会代发你的请求到 https://cnodejs.org/api/v1/topics 最后将获取的数据发送给你。

location.hash