Admin-Element 项目的 API 请求流程遵循以下步骤:
src/api/ 目录下按模块定义 API 接口axios 封装网络请求,添加拦截器在 src/utils/request.js 中创建 axios 实例并配置:
import axios from 'axios'
import { Message, Loading } from 'element-ui'
import store from '@/store'
import { getToken } from '@/utils/auth'
// 创建 axios 实例
const service = axios.create({
baseURL: process.env.VUE_APP_BASE_API, // API 基础路径
timeout: 10000, // 请求超时时间
headers: {
'Content-Type': 'application/json;charset=utf-8'
}
})
// 请求拦截器
service.interceptors.request.use(
config => {
// 显示加载动画
if (config.loading !== false) {
store.dispatch('app/showLoading')
}
// 自动添加 token
if (store.getters.token) {
config.headers['Authorization'] = `Bearer ${getToken()}`
}
return config
},
error => {
// 隐藏加载动画
store.dispatch('app/hideLoading')
console.error('请求错误:', error)
return Promise.reject(error)
}
)
// 响应拦截器
service.interceptors.response.use(
response => {
// 隐藏加载动画
store.dispatch('app/hideLoading')
const res = response.data
// 检查响应状态
if (res.code !== 200) {
// 显示错误消息
Message.error({
message: res.message || '操作失败',
duration: 3000
})
// 处理 token 过期等特殊情况
if (res.code === 401) {
// 跳转到登录页面
store.dispatch('user/logout').then(() => {
location.reload()
})
}
return Promise.reject(new Error(res.message || '操作失败'))
} else {
return res
}
},
error => {
// 隐藏加载动画
store.dispatch('app/hideLoading')
// 处理网络错误
let message = '网络请求失败'
if (error.response) {
const status = error.response.status
switch (status) {
case 400:
message = '请求参数错误'
break
case 401:
message = '未授权,请重新登录'
// 跳转到登录页面
store.dispatch('user/logout').then(() => {
location.reload()
})
break
case 403:
message = '拒绝访问'
break
case 404:
message = '请求地址不存在'
break
case 500:
message = '服务器内部错误'
break
default:
message = `请求失败 (${status})`
}
} else if (error.message.includes('timeout')) {
message = '请求超时'
}
// 显示错误消息
Message.error({
message: message,
duration: 3000
})
return Promise.reject(error)
}
)
export default service
API 接口按模块组织,存放在 src/api/ 目录下:
src/api/
├── index.js # API 入口文件
├── user.js # 用户相关接口
├── goods.js # 商品相关接口
├── order.js # 订单相关接口
└── ... # 其他模块接口
在 src/api/user.js 中定义用户相关接口:
import request from '@/utils/request'
export default {
// 登录
login(data) {
return request({
url: '/admin/login',
method: 'post',
data
})
},
// 获取用户信息
getUserInfo() {
return request({
url: '/admin/user/info',
method: 'get'
})
},
// 获取用户列表
getUserList(params) {
return request({
url: '/admin/user/list',
method: 'get',
params
})
},
// 修改用户信息
updateUser(data) {
return request({
url: '/admin/user/update',
method: 'put',
data
})
},
// 删除用户
deleteUser(id) {
return request({
url: `/admin/user/delete/${id}`,
method: 'delete'
})
}
}
在 src/api/index.js 中导出所有 API 模块:
import user from './user'
import goods from './goods'
import order from './order'
// 导出 API 模块
export default {
user,
goods,
order
}
// 带查询参数的 GET 请求
api.user.getUserList({
page: 1,
limit: 10,
keyword: 'test'
})
// 带请求体的 POST 请求
api.user.login({
username: 'admin',
password: '123456'
})
// 带请求体的 PUT 请求
api.user.updateUser({
id: 1,
username: 'newadmin',
nickname: '新管理员'
})
// 路径参数的 DELETE 请求
api.user.deleteUser(1)
后端 API 响应数据结构应遵循以下规范:
{
"code": 200, // 状态码,200 表示成功
"message": "操作成功", // 响应消息
"data": { ... } // 响应数据
}
// 在组件中调用 API
import api from '@/api'
export default {
methods: {
async fetchUserList() {
try {
const res = await api.user.getUserList({
page: this.page,
limit: this.limit
})
// 处理成功响应
this.userList = res.data.list
this.total = res.data.total
} catch (error) {
// 错误已在拦截器中处理,这里可以做额外处理
console.error('获取用户列表失败:', error)
}
}
}
}
async fetchData() {
try {
const res = await api.goods.getGoodsList(this.queryParams)
this.goodsList = res.data.list
this.total = res.data.total
} catch (error) {
// 错误处理
}
}
export default {
data() {
return {
loading: false,
goodsList: []
}
},
methods: {
async fetchData() {
this.loading = true
try {
const res = await api.goods.getGoodsList(this.queryParams)
this.goodsList = res.data.list
} catch (error) {
// 错误处理
} finally {
this.loading = false
}
}
}
}
对于频繁触发的请求,使用防抖或节流优化:
import { debounce } from 'lodash'
export default {
methods: {
// 使用防抖优化搜索请求
search: debounce(async function(query) {
try {
const res = await api.goods.searchGoods({ keyword: query })
this.searchResults = res.data
} catch (error) {
// 错误处理
}
}, 300)
}
}
对于可能重复触发的请求,使用取消令牌避免重复请求:
import axios from 'axios'
export default {
data() {
return {
cancelToken: null
}
},
methods: {
async fetchData() {
// 取消之前的请求
if (this.cancelToken) {
this.cancelToken.cancel('取消重复请求')
}
// 创建新的取消令牌
this.cancelToken = axios.CancelToken.source()
try {
const res = await api.goods.getGoodsList({
page: this.page,
limit: this.limit
}, {
cancelToken: this.cancelToken.token
})
this.goodsList = res.data.list
} catch (error) {
if (axios.isCancel(error)) {
console.log('请求已取消:', error.message)
} else {
// 错误处理
}
}
}
}
}
对于多个相同类型的请求,合并为一个请求:
// 批量获取数据
api.goods.batchGetGoodsInfo(ids)
Admin-Element 项目的 API 请求流程采用了统一的封装和处理机制,通过 axios 拦截器实现了请求和响应的统一处理,提高了代码的可维护性和可扩展性。开发者应遵循接口定义规范和最佳实践,确保 API 调用的安全性、可靠性和性能。