# html 基础

# 1. 前端跨域

# 1.1 为什么会有跨域

  • 由于浏览器的同源策略,会拦截不同源的资源进出。所以当我们需要从其他服务器收发消息的时候就需要进行跨域操作(同源是为了防止恶意操作)。

ps:ip、端口、协议的不同都会被认为是不同源

# 1.2 跨域的解决方式

# 1.2.1 jsonp

# 1.2.1.1 jsonp 原理

  • 浏览器虽然限制不同源的资源进出,但允许 js 资源的跨域访问。也就是说当一个页面的 js 请求另一个 js 资源的时候,另一个 js 资源可以对原 js 资源中的资源进行调用
  • jsonp 的原理其实就是通过 script 标签对 src 的不限制,通过 get 请求将固定参数发送到服务端,由服务端接收到参数并将需要发送给前端的参数拼接成为一个可执行的 js 代码后返回给前端执行。(本质就是通过 script 标签请求一个 js 资源到本地执行)

# 1.2.1.2 jsonp 实现

  • 服务端部分
// 这里是用express起了一个简单的node服务,就不赘述了
router.get("/jsonp", (req, res) => {
  const query = req.query || { msg: "没有传参" }; // 请求参数
  // 获取请求参数中的cb字段(也即回调函数的名称)
  const cb = req.query.cb;
  // 返回一段js,这里就是对回调函数的调用,其中的参数是json形式返回的
  res.send(`${cb}(${JSON.stringify({ message: "jsonp返回成功" })})`);
});
  • 前端部分
// 设置回调函数
window.callbackFunction = function (res) {
  console.log("jsonp返回值" + res.message);
};

// 创建script标签
const JSONP = document.createElement("script");
JSONP.type = "text/javascript";

// 设置服务资源请求地址,?后面是参数,这里只传了一个回调函数的名字
JSONP.src = "http://127.0.0.1:3333/api/jsonp?cb=callbackFunction";

// 挂载script标签到head标签上
document.getElementsByTagName("head")[0].appendChild(JSONP);
  • 这里也可以用 ajax 实现(这里 axios 是不支持 jsonp 方式的)

# 1.2.1.3 jsonp 优劣

  • jsonp 可以在几乎所有的浏览器中执行,对于一些老的浏览器也能适用,适配性比较好
  • jsonp 只能用于 get 请求,对于复杂的请求无法处理

# 1.2.2 cors

  • 浏览器端发送 http 请求的时候会在请求头中携带一个 origin 字段来表明当前请求属于哪个域(协议+域名+端口),此时当请求成功发送到后端服务器之后,如果当前请求的服务器允许请求域访问则会在返回请求头中加入 Access-Control-Allow-Origin:域名(如果为*则表示允许全部) 如果此时后端返回的头信息中该条值与请求域名相同则表明允许跨域,否则则无法跨域。

# 1.2.3 反向代理

  • 因为跨域问题是浏览器做的限制,它不存在于服务器与服务器之间,那么此时我们可以在本地启动一个服务将浏览器的请求转发到本地服务器中,再由本地服务器和外部服务器进行交互,由于 html 和本地服务器是同源所以此时跨域问题就不存在了。

# 1.2.4 总结

  • 一般地在开发环境中我们多采用反向代理的方式来处理跨域问题,实际生产环境中则是以 cors 为主,jsonp 的方式由于限制太大现在已经不怎么使用了。