本文提供相关源码,请放心食用,详见网页侧边栏或底部,有疑问请评论或 Issue
首先请检查下你的 Vue 版本,Vue2 和 Vue3 跨域方式不同,在命令行中输入 vue -V
,可以查看当前的 Vue 版本。
一、Vue2 版本
为了复现跨域问题,这里以访问 Ve2x 的一个公告API为例,当我们不做特殊处理,直接访问如下:
1 2 3 4 5 6 7
| this.$axios.get("https://www.v2ex.com/api/site/info.json") .then(res=>{ console.log(res) }) .catch(err=>{ console.log(err) })
|
当我们运行程序后,控制台报错如下:
可以看到浏览器拦截了我们的请求,因为我们跨域了,下面解决跨域问题。
Step1:配置BaseUrl
首先在main.js
中,配置下我们访问的Url前缀:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| import Vue from 'vue' import App from './App' import Axios from 'axios'
Vue.prototype.$axios = Axios Axios.defaults.baseURL = '/api' Axios.defaults.headers.post['Content-Type'] = 'application/json';
Vue.config.productionTip = false
new Vue({ el: '#app', components: { App }, template: '<App/>' })
|
关键代码是:Axios.defaults.baseURL = '/api'
,这样每次发送请求都会带一个/api
的前缀。
Step2:配置代理
修改config文件夹下的index.js
文件,在proxyTable
中加上如下代码:
1 2 3 4 5 6 7
| '/api':{ target: "https://www.v2ex.com/api", changeOrigin:true, pathRewrite:{ '^/api':'' } }
|
Step3:修改请求Url
修改刚刚的axios请求,把url
修改如下:
1 2 3 4 5 6 7
| this.$axios.get("/site/info.json") .then(res=>{ console.log(res) }) .catch(err=>{ console.log(err) })
|
Step4:重启服务
重启服务后,此时已经能够访问了:
原理:
因为我们给url加上了前缀 /api
,我们访问 http://127.0.0.1:19323/site/info.json
就当于访问了:http://127.0.0.1:19323/api/site/info.json
。(假设本地访问端口号为 19323)
又因为在 index.js
中的 proxyTable
中拦截了 /api
,并把 /api
及其前面的所有替换成了 target
中的内容,因此实际访问 Url 是https://www.v2ex.com/api/site/info.json
。
二、Vue3 版本
升级到 Vue3 后,会发现 Vue2 中存放配置的 config
文件夹没有了,大家不要慌张。可以在 package.json 文件的同级目录下创建 vue.config.js
文件。给出该文件的基础配置:
1 2 3 4 5 6 7 8 9 10 11 12 13
| module.exports = { outputDir: 'dist', assetsDir: 'assets', lintOnSave: false, devServer: { open: true, host: "localhost", port: '8081', https: false, hotOnly: false, proxy: null, } }
|
Vue3 解决跨域,内容只有第二步配置代理 和 Vue2 不同,其他的一致。
Step2:配置代理
修改 vue.config.js 中 devServer
子节点内容,添加一个 proxy
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| devServer: { open: true, host: "localhost", port: '8081', https: false, hotOnly: false, proxy: { '/api': { target: 'https://www.v2ex.com/api', changeOrigin: true, pathRewrite: { '^/api': '' } } }, }
|
三、番外
当然,跨域问题也可以由后端解决,将下面这个过滤器加入程序即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
| import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException;
public class CorsFilter implements Filter { @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletResponse response = (HttpServletResponse) res; HttpServletRequest request = (HttpServletRequest) req;
String origin = request.getHeader("Origin"); if(StringUtils.isNotBlank(origin)) { response.setHeader("Access-Control-Allow-Origin", origin); }
String headers = request.getHeader("Access-Control-Request-Headers"); if(StringUtils.isNotBlank(headers)) { response.setHeader("Access-Control-Allow-Headers", headers); response.setHeader("Access-Control-Expose-Headers", headers); }
response.setHeader("Access-Control-Allow-Methods", "*"); response.setHeader("Access-Control-Max-Age", "3600"); response.setHeader("Access-Control-Allow-Credentials", "true"); chain.doFilter(request, response); }
@Override public void init(FilterConfig filterConfig) {
}
@Override public void destroy() { }
}
|