Para integrar Axios en un proyecto Vue3 con Vite y TypeScript, se configura un cliente HTTP personalizado con interceptores para manejar tokens y errores. A continuación, se define una estructura para las operaciones API y ejemplos de uso en componentes.
import axios, { InternalAxiosRequestConfig, AxiosResponse } from 'axios'
import { ElMessage, ElMessageBox } from 'element-plus'
import { useUserStore } from '@/stores/user'
const httpClient = axios.create({
baseURL: import.meta.env.VITE_API_BASE_URL,
timeout: 30000
})
httpClient.interceptors.request.use(
(config: InternalAxiosRequestConfig) => {
const userStore = useUserStore()
if (userStore.token) {
config.headers.set('Authorization', `Bearer ${userStore.token}`)
}
return config
},
(error) => Promise.reject(error)
)
httpClient.interceptors.response.use(
(response: AxiosResponse) => {
const userStore = useUserStore()
const { code, message } = response.data
if (response.data instanceof ArrayBuffer || response.data instanceof Blob) {
return response
}
if (code === 401) {
userStore.logout().then(() => {
window.location.href = '/login'
})
return Promise.reject('Sesión inválida o expirada. Por favor, inicie sesión nuevamente.')
} else if (code === 500) {
ElMessage.error(message || 'Error del sistema')
} else if (code !== 200) {
ElMessage.warning(message)
} else {
return response.data
}
},
(error) => {
const { status, data } = error.response || {}
if (status === 401) {
ElMessageBox.alert('La sesión ha expirado. Por favor, inicie sesión de nuevo.', 'Aviso', {
confirmButtonText: 'Aceptar',
callback: () => {
window.location.href = '/login'
}
})
} else {
ElMessage({
message: data?.message || 'Error del sistema',
type: 'error'
})
}
return Promise.reject(new Error(data?.message || 'Error'))
}
)
export default httpClient
Se crea un archivo de API, por ejemplo tasksApi.ts, con funciones para las solicitudes HTTP.
import httpClient from '@/utils/httpClient'
export function createTask(data: Record<string, unknown>) {
return httpClient({
url: '/tasks/create',
method: 'post',
data
})
}
export function fetchTasks(params: Record<string, unknown>) {
return httpClient({
url: '/tasks/list',
method: 'get',
params
})
}
export function downloadTasks(params: Record<string, unknown>) {
return httpClient({
url: '/tasks/download',
method: 'post',
responseType: 'blob',
params
})
}
export function uploadTasks(params: Record<string, unknown>, formData: FormData) {
return httpClient({
url: '/tasks/upload',
method: 'post',
headers: {
'Content-Type': 'multipart/form-data'
},
params,
data: formData
})
}
En el componente Vue, se utilizan estas funciones para realizar operaciones. Para la descarga, se requiere el paquete file-saver, instalable mediante npm.
import { fetchTasks, uploadTasks, downloadTasks } from '@/api/tasksApi'
import { saveAs } from 'file-saver'
const loadData = async () => {
const params = { id: 1 }
const response = await fetchTasks(params)
// Procesar datos de respuesta
}
const handleFileUpload = (file: File) => {
const formData = new FormData()
formData.append('file', file)
const params = { id: 1 }
uploadTasks(params, formData).then(res => {
// Manejar éxito de carga
})
}
const handleFileDownload = () => {
const params = { id: 1 }
downloadTasks(params).then(blob => {
saveAs(blob, `datos-exportados.xlsx`)
})
}