vue项目中使用接口的方式
第一种
案例为vue-element-admin模板里的写法。使用封装之后的axios,一般二次封装之后的文件在模板项目utils文件下的request.js,在该文件中引入axios,配置基础路径、请求拦截器、响应拦截器等等,然后在api文件夹之下去写接口(不需要向外暴露),最后在views页面中调用接口即可。不在main.js中映入。
request.js文件
// 请求拦截器就在此处
import axios from 'axios'
import { MessageBox, Message } from 'element-ui'
import store from '@/store'
import { getToken } from '@/utils/auth'
// import errorCode from '@/utils/errorCode'
axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'
const service = axios.create({
baseURL: process.env.VUE_APP_BASE_API, // 基础路径
timeout: 30000 // 请求超时时间 毫秒 1秒=1000毫秒
})
// 使用 request.interceptors.request.use() 函数就可以进行请求拦截器的配置
// request interceptor:请求拦截器:就是在使用该实例发送请求时,可以在这里进行一些设置,通常用来携带token之类的功能
service.interceptors.request.use(
// 在发送请求之前做什么
config => {
if (store.getters.token) {
config.headers['Authorization'] = 'Bearer ' + getToken()
}
return config //返回这个配置对象,如果没有返回,这个请求就不会发送出去
},
// 对请求错误做些什么
error => {
this.$message({
message: '网络拦截错误!!!',
type: 'warning'
});
return Promise.reject(error)
}
)
// response interceptor:响应拦截器
service.interceptors.response.use(
// 对响应数据做些什么
response => {
const res = response.data
if (res.code >= 300) {
Message({
message: res.message || 'Error',
type: 'error',
duration: 5 * 1000
})
} else {
return response
}
},
// 对错误信息做些什么 数据是经过axios封装了的,所以我们一般直接取里面的data
error => {
if (!error.response) {
Message({
message: '网络连接异常!',
type: 'error',
duration: 5 * 1000
})
return Promise.reject(error)
}
// 登录失败 and 响应状态码是 401 => 就应该重新登录
else if (error.response.status === 401 && error.response.data.code === "LOGIN_FAIL") {
// to re-login
// MessageBox.confirm('您已退出登录,您可以取消以留在此页面,或重新登录', '登陆提示', {
// confirmButtonText: '重新登录',
// cancelButtonText: '取消',
// type: 'warning'
// }).then(() => {
// store.dispatch('user/logout').then(() => {
// location.reload()
// })
// })
Message({
message: error.response.data.message,
type: 'error'
})
return Promise.reject(error)
}
// 令牌无效 and 响应状态码是 401
else if (error.response.data.code == 'TOKEN_INVALID' && error.response.status === 401) {
store.dispatch('user/logout').then(() => {
location.reload()
})
}
// 状态码大于 500 时
else if (error.response.status >= 500) {
Message({
message: error.response.data.message,
type: 'error'
})
return Promise.reject(new Error(error.response.status))
}
return Promise.reject(error)
}
)
export default service
api文件夹之下的某个文件
import request from '@/utils/request'
// 用户管理接口
// 用户列表
export function getuserList(query) {
return request({
url: '/admin/users',
method: 'get',
params:query
})
}
// 用户状态修改
export function UpdateUser(data){
return request({
url:'/admin/user/'+ data.id,
method: 'PATCH',
data:data
})
}
在页面中引用接口
// 组件中引用
import { getJson } from "@/api/user";
import { getuserList, UpdateUser } from "@/api/usermanage/index";
getList() {
getuserList(this.queryParams).then((res) => {
this.tableData = res.data.data;
this.queryParams.total = res.data.total;
console.log("用户列表数据", res.data.data);
});
},
//获取公司列表
getType() {
getJson().then((res) => {
this.companys = res.data.company_list;
});
},
第二种
在main.js文件中引入,把所有的接口都挂载带vue的原形上,因此直接在页面中使用就行,不用再导入api文件(但是需要在api文件中向外暴露接口)。也仍需要二次封装的axios
request.js文件
import axios from 'axios'
import { MessageBox, Message } from 'element-ui'
import store from '@/store'
import { getToken } from '@/utils/auth'
// create an axios instance
const service = axios.create({
baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
// withCredentials: true, // send cookies when cross-domain requests
timeout: 5000 // request timeout
})
//请求拦截器:携带的token字段
service.interceptors.request.use(
config => {
// do something before request is sent
if (store.getters.token) {
// let each request carry token
// ['X-Token'] is a custom headers key
// please modify it according to the actual situation
config.headers['token'] = getToken()
}
return config
},
error => {
// do something with request error
console.log(error) // for debug
return Promise.reject(error)
}
)
//响应拦截器
service.interceptors.response.use(
/**
* If you want to get http information such as headers or status
* Please return response => response
*/
/**
* Determine the request status by custom code
* Here is just an example
* You can also judge the status by HTTP Status Code
*/
response => {
const res = response.data
//服务器响应失败在干什么,因为咱们真实服务器返回code 20000也有可能200
if (res.code !== 20000 && res.code!=200) {
Message({
message: res.message || 'Error',
type: 'error',
duration: 5 * 1000
})
// 50008: Illegal token; 50012: Other clients logged in; 50014: Token expired;
if (res.code === 50008 || res.code === 50012 || res.code === 50014) {
// to re-login
MessageBox.confirm('You have been logged out, you can cancel to stay on this page, or log in again', 'Confirm logout', {
confirmButtonText: 'Re-Login',
cancelButtonText: 'Cancel',
type: 'warning'
}).then(() => {
store.dispatch('user/resetToken').then(() => {
location.reload()
})
})
}
return Promise.reject(new Error(res.message || 'Error'))
} else {
//服务器相应成功干什么
return res
}
},
error => {
console.log('err' + error) // for debug
Message({
message: error.message,
type: 'error',
duration: 5 * 1000
})
return Promise.reject(error)
}
)
export default service
某个api文件以及其向外暴露接口的文件
//sku模块
import request from '@/utils/request';
//sku列表的接口
///admin/product/list/{page}/{limit}
export const reqSkuList = (page,limit)=>request({url:`/admin/product/list/${page}/${limit}`,method:'get'});
//上架
///admin/product/onSale/{skuId}
export const reqSale = (skuId)=>request({url:`/admin/product/onSale/${skuId}`,method:'get'});
//下架
///admin/product/cancelSale/{skuId}
export const reqCancel = (skuId)=>request({url:`/admin/product/cancelSale/${skuId}`,method:'get'});
//获取SKU详情的接口
///admin/product/getSkuById/{skuId} get
export const reqSkuById = (skuId)=>request({url:`/admin/product/getSkuById/${skuId}`,method:'get'});
向外暴露接口的文件
//将四个模块请求的接口函数统一暴露
import * as trademark from './product/tradeMark';
import * as attr from './product/attr';
import * as spu from './product/spu';
import * as sku from './product/sku';
//引入权限相关的接口文件
import * as user from './acl/user';
import role from './acl/role';
import permission from './acl/permission'
//对外暴露
export default {
trademark,
attr,
sku,
spu,
user,
role,
permission
}
在main.js文件中引入
//引入相关API请求接口
import API from '@/api';
//组件实例的原型的原型指向的是Vue.prototype
//任意组件可以使用API相关的接口
Vue.prototype.$API =API;
在页面中使用,不用再导入接口,直接使用即可
let result = await this.$API.trademark.reqTradeMarkList(page, limit);