在本地开发环境下做vue前后端分离的项目,开发及项目上线会遇到一个切换服务器环境导致的跨域问题。解决跨域问题可以由以下几个步骤。
首先前提假设
前端服务器地址(http://localhost:8080) 这个也是默认的前端开发地址
后端API服务器地址(http://localhost:3000) 本地开发环境(express),前端服务器和后端服务器在同一个地址,但是端口不同,这个情况仍然是面临跨域问题。
在脚手架初始化完毕之后,一般都以下几个改造过程
配置axios的全局的默认配置
// 文件路径 src/config/index.js
// 全局的axios基础配置,一般配置的是开发API和生产API地址
export default {
baseURL: {
dev: "/api", //开发后台服务器后台,注意这里的配置 不是 http://localhost:3000
pro: "", //上线后的接口地址
},
};
封装axios
// 文件路径 src/api/axios.js
// 封装axios 包含了拦截器的配置
import axios from "axios";
import config from "@/config/index.js";
const baseURL =
process.env.NODE_ENV === "development"
? config.baseURL.dev
: config.baseURL.pro;
class HttpRequest {
// 实例构造函数
constructor(baseURL) {
this.baseURL = baseURL;
this.queue = {}; //请求队列
}
//获取请求的基础配置
getInsideConfig() {
// 全局写死的配置
const config = {
baseURL: this.baseURL,
headers: {},
};
return config;
}
// 拦截器方法封装
// instance 是axios 实例
// url 是拦截的url
interceptors(instance, url) {
// 请求拦截
instance.interceptors.request.use(
(config) => {
// Do something before request is sent
// 修改请求的配置
console.log("拦截 请求");
// config 里面的data 做简单配置
//config.data = {
// msg: "OK",
// };
console.log(config);
return config;
},
(error) => {
// Do something with request error
// return Promise.reject(error);
console.log(error);
return Promise.reject(error);
}
);
// 响应拦截
instance.interceptors.response.use(
(response) => {
// Do something before response is sent
console.log("拦截 响应");
console.log(response);
return response;
},
(error) => {
// Do something with response error
// return Promise.reject(error);
console.log(error);
return Promise.reject(error);
}
);
}
// 请求方法封装
// 返回 axios 实例(带配置)
request(options) {
const instance = axios.create();
// 合并默认的请求参数和外部传入的请求参数
// 基础配置和额外配置合并
options = Object.assign(this.getInsideConfig(), options);
this.interceptors(instance, options.url);
return instance(options);
}
}
const axiosObj = new HttpRequest(baseURL);
export default axiosObj;
使用方法:
axiosObj.request({
url:'/path', // url配置,
method:'get' // http 请求方法
})
整合http请求
// 文件路径 src/api/data.js
// 项目中使用的所有的API请求都写在这里
// 导入前面封装的axios封装对象
import axios from "@/api/axios.js";
// 广告图
export const getBannerData = () => {
return axios.request({
url: "banner",
method: "get",
});
};
vue.config.js 文件配置(脚手架配置)
// 文件路径 src/vue.config.js
module.exports = {
devServer: {
proxy: {
//只有部分请求使用代理,一般是请求API资源
// 所以一般设置请求api的走代理
"/api": {
target: "http://localhost:3000", //真正的后端API服务器
// 为什么要重写代理的路径?
// 因为实际请求的资源 比如 http://localhost:3000/banner
// 实际资源路径不含/api
pathRewrite: { "^/api": "" }, //重写 /api 替换为 空
},
},
},
};
这段配置的含义是,在开发服务器端控制需要代理的路径,如果包含/api
,则走代理模式,真实访问的后端服务器地址则是target
属性设置的。由于真实的API地址不含/api
,所以需要通过pathRewrite
属性来配置一下。
前端请求的地址是axios的baseURL
和url
"/api"+"/banner"
"/api"+"banner"
上面请求的地址触发了开发服务器的代理机制,因为有/api
所以会访问后台的http://localhost:3000
,再经过地址重写(pathRewrite: { "^/api": "" }
),所以代理实际访问的是http://localhost:3000/banner