持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第3天,点击查看活动详情
前段项目下,处理跨域是一个很正常的问题;在vue脚手架下面处理就更为常见了;那么要怎么去处理这个很常见的问题呢?
1.在src下面新建api/index.js,然后将对应的js文件复制进去,并且放到原型里面
// 配置API接口地址
import Vue from 'vue'
// import { Toast } from 'vant';
// import store from '../store/index';
// Vue.use(Toast);
// 打包时要注释
// var root ='/api'
// 引用axios
var axios = require('axios');
// 自定义判断元素类型JS
function toType(obj) {
return ({}).toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase()
}
// 参数过滤函数
function filterNull(o) {
for (var key in o) {
if (o[key] === null) {
delete o[key]
}
if (toType(o[key]) === 'string') {
o[key] = o[key].trim()
} else if (toType(o[key]) === 'object') {
o[key] = filterNull(o[key])
} else if (toType(o[key]) === 'array') {
o[key] = filterNull(o[key])
}
}
return o
}
/**
* 提示函数
* 禁止点击蒙层、显示一秒后关闭
*/
const tip = msg => {
Toast({
message: msg,
duration: 1000,
forbidClick: true
});
}
/**
* 跳转登录页
* 携带当前页面路由,以期在登录页面完成登录后返回当前页面
*/
const toLogin = () => {
router.replace({
path: '/login',
query: {
redirect: router.currentRoute.fullPath
}
});
}
/**
* 请求失败后的错误统一处理
* @param {Number} status 请求失败的状态码
*/
const errorHandle = (status, other) => {
// 状态码判断
switch (status) {
// 401: 未登录状态,跳转登录页
case 401:
toLogin();
break;
// 403 token过期
// 清除token并跳转登录页
case 403:
tip('登录过期,请重新登录');
// localStorage.removeItem('token');
// store.commit('loginSuccess', null);
setTimeout(() => {
toLogin();
}, 1000);
break;
// 404请求不存在
case 404:
tip('请求的资源不存在');
break;
default:
}}
// 创建axios实例
// var instance = axios.create({ timeout: 1000 * 12});
// 设置post请求头
//axios.defaults.headers.post['Content-Type'] = 'application/json';
/**
* 请求拦截器
* 每次请求前,如果存在token则在请求头中携带token
*/
//axios.interceptors.request.use(
//config => {
// 登录流程控制中,根据本地是否存在token判断用户的登录情况
// 但是即使token存在,也有可能token是过期的,所以在每次的请求头中携带token
// 后台根据携带的token判断用户的登录情况,并返回给我们对应的状态码
// 而后我们可以在响应拦截器中,根据状态码进行一些统一的操作。
// const token = sessionStorage.token;
// token && (config.headers.Authorization = token);
// return config;
// },
// error => Promise.error(error)
// )
axios.defaults.timeout = 10000
// 响应拦截器
axios.interceptors.response.use( res => res.status === 200 ? Promise.resolve(res) : Promise.reject(res),
// 服务器状态码不是2开头的的情况
// 这里可以跟你们的后台开发人员协商好统一的错误状态码
// 然后根据返回的状态码进行一些操作,例如登录过期提示,错误提示等等
// 下面列举几个常见的操作,其他需求可自行扩展
// 请求失败
error => {
const { response } = error;
if (response) {
// 请求已发出,但是不在2xx的范围
errorHandle(response.status, response.data.message);
return Promise.reject(response);
} else {
// 处理断网的情况
// eg:请求超时或断网时,更新state的network状态
// network状态在app.vue中控制着一个全局的断网提示组件的显示隐藏
// 关于断网组件中的刷新重新获取数据,会在断网组件中说明
// setTimeout(() => {
// Toast({
// message: "暂无网络,请稍后重试",
// duration: 1000,
// forbidClick: true
// });
// }, 500);
store.commit('changeNetwork', false);
}
});
function apiAxios(method, url, params, success, failure){
if (params) {
params = filterNull(params)
}
// if (process.env.NODE_ENV == 'development'){
// axios.defaults.baseURL = 'http://39.96.24.162:10000';
// } else if (process.env.NODE_ENV == 'testing'){
// axios.defaults.baseURL = 'http://39.96.24.162:10000';
// } else if (process.env.NODE_ENV == 'production') {
// axios.defaults.baseURL = 'http://59.110.220.161:9000';
// }
axios({
method: method,
url: url,
headers: {
"Content-Type": "application/json",
Authorization: localStorage.token
},
data: method === 'POST' || method === 'PUT' ? params : null,
params: method === 'GET' || method === 'DELETE' ? params : null,
// 打包时要注释
// baseURL:root,
withCredentials: false,
})
.then(function (res) {
if (res.status === 200) {
if (success) {
success(res.data);
Toast.clear();
}
} else {
if (failure) {
failure(res.data);
} else {
// Toast.loading({
// duration:1000,
// forbidClick: true,
// loadingType: 'spinner',
// message:JSON.stringify(res.data),
// });
// Message({
// showClose: true,
// message: 'error: ' + JSON.stringify(res.message),
// type: 'error',
// duration: 2000
// })
// this.$Message.error('error: ' + JSON.stringify(res.data));
// window.alert('error: ' + JSON.stringify(res.data))
}
}
})
.catch(function (err) {
let res = err.response;
if (err) {
// loadinginstance.close();
// Indicator.close();
// Toast.loading({
// duration:1000,
// forbidClick: true,
// loadingType: 'spinner',
// message: JSON.stringify(res.message),
// });
// Message({
// showClose: true,
// message: res.data.non_field_errors, // res.data.non_field_errors
// type: 'error',
// duration: 2000
// })
// window.alert('api error, HTTP CODE: ' + res.status)
}
})
}
// 返回在vue模板中的调用接口
export default {
get: function (url, params, success, failure) {
return apiAxios('GET', url, params, success, failure)
},
post: function (url, params, success, failure) {
return apiAxios('POST', url, params, success, failure)
},
put: function (url, params, success, failure) {
return apiAxios('PUT', url, params, success, failure)
},
delete: function (url, params, success, failure) {
return apiAxios('DELETE', url, params, success, failure)
}
}
2.添加本地代理,处理跨域(注意只在本地有效,打包不走这个,放线上还是会跨域)
3.打开api文件夹下面的index.js(注意,这两个打包的时候要注释掉)
4.然后页面开始调接口
5.配置测试环境和生产环境(并且在package.json文件配置命令)
6.然后将文件夹夹放到和后端的数据同一个域下(同一个服务器)测试,看到数据就可以了