vue3中使用axios

1、问题:

在vue2中axios通常是经过封装的后挂载使用的,来处理token及报错处理,比如

//main.js
import ajax from '@/axios.js'
Vue.prototype.ajax = ajax

在项目中使用也很方便this.ajax就行了,那vue3中是如何简单、便捷的封装并使用呢

2、思路:

vue3中使用axios并不难,封装,然后使用就这两步,痛点在于多了setup很难像vue2一样简单、便捷的使用

在网上查了一圈,有通过app.config.globalProperties、getCurrentInstance挂载使用的,有用vue-axios的,还有provide、inject依赖注入的

这些方式都比vue2多了一步,即先引入,再调用,那有没有更好的方法呢?有,且很简单

目前的vue3项目普遍安装了unplugin-auto-import这个库,这个库大家都很熟悉,就是自动import的,如果能够自动引入我们封装好的axios方法不是就很简单、便捷了吗

查看unplugin-auto-import文档,里面有//custom这么一种使用方式来引入

3、实现

先新建一个ajax.js来封装我们的axios

//ajax.js
import axios from 'axios'
import router from '@/router'

// 设置代理
const proxy = '/api'

// 设置token
const setToken = headers => {
    let token = localStorage.getItem('token')
    if (token) {
        headers.authorization = 'Bearer ' + token
    }
}

// 处理响应错误
const handleResponse = err => {
    console.log('handleResponse', err)
    let res = err.response
    let errArr = [401]
    if (errArr.includes(res.status)) {
        localStorage.removeItem('token')
        router.push('/')
    }
    if (res.data) {
        ElMessage.closeAll()
        ElMessage.error({
            showClose: true,
            message: res.data.msg,
        })
    }
    return Promise.reject(err)
}

// 处理请求数据
const handleData = res => {
    console.log('handleData', res)
    if (res.data) {
        if (res.data.code == 200) {
            return res.data.data
        }
        else if (res.data.code == 401) {
            localStorage.removeItem('token')
            router.push('/')
        }
        else {
            ElMessage.closeAll()
            ElMessage.error({
                showClose: true,
                message: res.data.msg,
            })
            return Promise.reject(res.data)
        }
    }
}

// 处理上传数据
const handleUpFileData = data => {
    if (data instanceof Blob) {
        let formData = new FormData()
        formData.append('file', data)
        return formData
    }
    if (data instanceof FormData) {
        return data
    }
    return null
}

// 处理下载文件
const handleDownFile = res => {
    let url = window.URL.createObjectURL(res.data)
    let fileName = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/.exec(res.headers['content-disposition'])[1].replace(/['"]/g, '')
    let a = document.createElement('a')
    a.href = url
    a.download = fileName
    a.click()
    a.remove()
    window.URL.revokeObjectURL(url)
}

// 封装get
function get(url, params, headers = {}) {
    url = proxy + url
    setToken(headers)
    return axios.get(url, {
        params,
        headers,
    }).then(handleData, handleResponse)
}

// 封装post
function post(url, params, headers = {}) {
    url = proxy + url
    setToken(headers)
    return axios.post(url, params, { headers }).then(handleData, handleResponse)
}

// 封装上传文件
function upFile(url, params, headers = {}) {
    url = proxy + url
    setToken(headers)
    params = handleUpFileData(params)
    if (!params) return new Error('参数不正确')
    return axios.post(url, params, { headers }).then(handleData, handleResponse)
}

// 封装下载文件
function downFile(url, method, data, headers = {}) {
    url = proxy + url
    setToken(headers)
    if (method == 'get') return axios.get(url, {
        headers,
        responseType: 'blob',
    }).then(handleDownFile, handleResponse)
    if (method == 'post') return axios.post(url, data, {
        headers,
        responseType: 'blob',
    }).then(handleDownFile, handleResponse)

}
export default {
    get,
    post,
    upFile,
    downFile,
}

到vite.config.js设置使用unplugin-auto-import来自动引入

//vite.config.js
...
plugins: [
    ...
    AutoImport({
        imports: [
            'vue',
            'vue-router',
            { '.src/utils/ajax': [['default', 'ajax']] }//等同于import ajax from '.src/utils/ajax'
        ], 
        resolvers: [ElementPlusResolver(),],
    }), 
    ... 
] 
...
vue组件的setup中使用
<script setup >
let go = () => {
    ajax.get('/article/getArticle').then(res => {
        console.log(res)
    })
}
</script>

<template>
    <div @click="go">点击</div>
</template>
posted @ 2023-04-16 18:29  Pavetr  阅读(566)  评论(0编辑  收藏  举报