跨域是前端新手最大的拦路虎。先把它想成"别人家的店不让你进":你在自己家的店(5500 端口)里逛,想溜到隔壁店(3000 端口)拿东西,浏览器说"不行,你不是这家店的人,我不让你拿"。这就是同源策略——浏览器自带的安全机制。
判断"是不是同一家店"要看三样东西:协议(http 还是 https)、域名/IP(是谁)、端口号(几号门)。三样全一样才叫"同源",有任何一个不一样就是"跨域",浏览器就拦你。本地开发必须用 Live Server 打开页面,绝对不能双击 HTML 文件。
同源策略是浏览器自带的安全保护机制,用来防止恶意网站偷偷读你别的网站的数据。就像酒店的门禁卡:你只能进你住的那栋楼,不能刷进隔壁楼的房间。
判断"同源"(同一家店)需要三样全部相同,有任何一个不同就是"跨域":
// 判断同源需要同时满足 3 项全部相同: // 1. 传输协议:http / https / file(本地文件) // 2. 域名或 IP:127.0.0.1 / localhost / www.xxx.com // 3. 端口号:3000 / 5500 / 8080 // ===== 对比看看 ===== // ✅ 同源: // 页面:http://127.0.0.1:5500/index.html // 请求:http://127.0.0.1:5500/list.html // → 协议一样(http)、IP一样(127.0.0.1)、端口一样(5500) → 同源! // ❌ 跨域1:端口不同 // 页面:http://127.0.0.1:5500/index.html // 请求:http://127.0.0.1:3000/api // → 端口 5500 ≠ 3000 → 跨域! // ❌ 跨域2:协议不同 // 页面:file:///C:/demo/index.html(双击打开的) // 请求:http://127.0.0.1:3000/api // → 协议 file ≠ http → 跨域!
如果你在 Network 面板的 Response 里什么都看不到,但 Console 里有红字 CORS 报错,那就是跨域——因为浏览器在网络层面就把响应拦住了,Network 里看不到内容。跨域报错去 Console 看,不去 Network 看。
很多同学不理解"我就双击个 HTML 怎么就跨域了"。原因很简单:双击打开的页面,地址栏协议是 file://(本地文件协议),而后端接口是 http://(网络协议)——协议不一样,浏览器立刻拦住你。
// 双击打开的页面: // 地址栏:file:///C:/Users/xxx/demo.html // 协议 = file(本地文件) // 你发的请求: // 接口地址:http://127.0.0.1:3000/api/user // 协议 = http(网络) // 协议不一样 → 同源策略拦截 → 请求发不出去
所以写前端页面、调试 AJAX 接口时,绝对禁止双击 HTML 打开。必须用 VS Code 的 Live Server 插件——它会帮你起一个本地小服务器,地址变成 http://127.0.0.1:5500,协议统一成 http,file 协议的跨域问题就解决了。但要注意:如果前后端端口不同(比如前端 5500、后端 3000),仍然跨域,那得后端配 CORS。
很多新手一看到跨域就疯狂改自己的前端代码,其实根本没用。跨域是浏览器给前端页面加的限制,但解决方案在后端手里——就像你进不了别人的店,得让那家店的老板开门,你自己在门口撬锁没用。
// 1. 后端主流解决方案:配置 CORS(跨域资源共享) // 后端加一个响应头,告诉浏览器"允许这个前端域名来访问" // 这是最正规、最常用的办法 // 2. 前端能做的(只是辅助手段,不能根治): // a. 开发阶段用代理(webpack/vite 配置 proxy) // b. JSONP(只支持 GET,现在基本不用了) // 3. 出现跨域报错,第一反应: // → 截图发给后端同学,让他配 CORS // → 不要自己在前端瞎折腾
如果你试图在前端代码里硬绕跨域,比如改 xhr 的属性、加什么特殊请求头——大概率没用。因为跨域是浏览器层面的安全限制,前端代码绕不过去,根源和解决方案都在后端。
接口请求失败了别急着慌,按这四步一步一步查:
// 第一步:核对接口 URL 地址 // 检查拼写、路径大小写、斜杠有没有多写少写 // 常见错:/api/userlist 写成 /api/userList(大小写不一致) // 第二步:区分 GET/POST 传参位置 // GET → 参数拼在 URL 上(?page=1&size=10) // POST → 参数放在 send 里面 // 常见错:POST 参数忘了塞 send,拼到 URL 上去了 // 第三步:Network 面板看 status 状态码 // F12 → Network → 筛选 XHR // 404 = 地址错了(后端没这个接口) // 500 = 后端代码报错(告诉后端查日志) // 403 = 没权限(token 过期了?) // 200 = 网络通了,但还要看业务码 // 第四步:打印 responseText // console.log(xhr.responseText) // 看后端返回的错误提示文字是什么,照着提示修
配合 Network 面板使用:F12 → Network → 点 XHR 筛选 → 看 General(地址和状态码)/ Request Headers(请求头)/ Query String Parameters(GET 参数)/ Response(返回内容)。四步按顺序查,90% 的接口问题都能定位。
可能在什么地方用:
① 前端调后端接口时遇到跨域,找后端配 CORS;② 本地开发用 Live Server 避免 file 协议跨域;③ 接口请求失败时用排错四步法定位问题。
常见的问题:
① 双击打开 HTML,Console 一片红——file 协议跨域;② 前端 5500 端口调后端 3000 端口,跨域——前端改代码没用;③ 接口返回 404——URL 拼错了;④ 接口返回 200 但数据不对——没看业务码。
解决思路:
① 先确认页面是用 Live Server 打开的(地址栏是 http:// 开头);② 有 CORS 报错就找后端配,别自己改前端;③ 404 查 URL 拼写;④ 200 了还不对,打印 xhr.responseText 看后端到底返回了什么。
练习四:跨域问题验证——复制上一节的 GET 请求代码:
① 直接双击打开 HTML,观察 Console 是不是有跨域报错,把报错信息记下来;② 用 VS Code 右键"Open with Live Server"打开同一页面,观察请求是不是成功了;③ 在注释里写清楚:为什么双击会跨域?为什么 Live Server 能解决?