在Vue中是如何封装axios

 更新时间:2021年10月9日 12:00  点击:2450

1、安装

npm install axios; // 安装axios

1、引入

import axios from 'axios'

3、接口根地址

const baseUrl = API_BASE_URL // 由webpack的插件DefinePlugin注入

webpackConfig
    .plugin('define')
        .use(require('webpack/lib/DefinePlugin'), [{
            // NODE_ENV 环境变量,开发环境为: 'development', 为了保证测试环境打的包与生产环境一致,测试环境和生产环境都为'production'
            'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
            // 当前应用的环境(开发环境为: 'dev',测试环境为: 'test', 生产环境为: 'prod')
            'process.env.APP_ENV': JSON.stringify(process.env.APP_ENV),
            // 后台接口请求地址
            'API_BASE_URL': JSON.stringify(config.meshProp('apiBaseUrl')),
            // 首页路径
            'APP_INDEX_PATH': JSON.stringify(indexPath),
            // 路由模式
            'APP_ROUTER_MODE': JSON.stringify(config.meshProp('routerMode')),
            // 是否使用Element组件库
            'APP_USE_ELEMENT': JSON.stringify(config.meshProp('useElement')),

}])


config.js:配置一些系统名称,api根路径等

const path = require('path')
const os = require('os')
const packageName = 'focm' // 项目包名称
const localIP = getLocalIP() // 本地IP地址

module.exports = {
    // 默认配置
    default: {
        // 系统名称,用于设置页面 head 中 title
        appName: 'xxxxx',
        // 是否为多页应用
        isMulti: false,
        // 是否支持移动端
        isMobile: false,
        // 是否使用Element组件库(https://element.eleme.cn/#/zh-CN/)
        useElement: true,
        // 路由模式(值为hash 或 history, 参考:https://router.vuejs.org/)
        routerMode: 'hash',
        // 接口请求根路径
        apiBaseUrl: '',
        ....
    },
    // 开发环境的配置
    dev: {
        apiBaseUrl: '/api',
        host: localIP,
        port: 8080,
        autoOpenBrowser: true, // 是否自动打开浏览器
        writeToDisk: false, // 是否将生成的文件写入磁盘
        proxyTable: {
            '/api': {
                target: 'http://focm-web.focms.paas.test',
                changeOrigin: true
                }
            }
    },
    // 测试环境的配置
    test: {
        // 接口请求根路径
        apiBaseUrl: '/focm',
        outputRoot: path.resolve(__dirname, 'dist/test'),
        publish: {
            remoteHost: 'x.x.x.x',
            remotePort: '22',
            remoteUsername: 'qinglianshizhe',
            remotePassword: 'xxxxxx',
            remoteAppRoot: `/xxx/xxx/${packageName}`,
            webUrl: 'http://xxxxx.com/'
        }
    },
    // 生产环境的配置
    prod: {
        ...
    }
}

// 获取本地IP
function getLocalIP () {
    let interfaces = os.networkInterfaces()
    for(let devName in interfaces){
        let iface = interfaces[devName]
        for(let i=0;i<iface.length;i++){
            let alias = iface[i];
            if(alias.family === 'IPv4' && alias.address !== '127.0.0.1' && !alias.internal){
                return alias.address;
            }
        }
    }
    return 'localhost'
}

我们继续来封装axios

/**
 * 业务异常类
 */

class BusinessError extends Error {
    constructor (code, message, data) {
        super(message)
        this.code = code
        this.name = 'BusinessError'
        this.data = data
    }
}
/**
 * 系统异常类
 */
class SystemError extends Error {
    constructor (code, message, data) {
        super(message)
        this.code = code
        this.name = 'SystemError'
        this.data = data
    }
}
// axios 配置
axios.defaults.timeout = 10000
axios.defaults.headers.post['Content-Type'] = 'application/json;charset=UTF-8'

// 执行 POST 请求
function post (option, vm) {
    option.method = 'POST'
    return http(option, vm)
}

// 执行 GET 请求
function get (option, vm) {
    option.method = 'GET'
    return http(option, vm)
}

// 下载请求
function download (option, vm) {
    option.method = option.method || 'GET'
    option.isDownload = true
    option.responseType = 'blob'
    return http(option, vm)
    }

/**
* 请求后台接口
* @param option 参数
* url: 请求路径(会拼接到baseUrl后面,“/” 开头)
* data: 请求参数对象
* timeout: 请求超时时间(默认为:10000,即10秒)
* toastError: 自动提示业务异常信息,默认为true,为false时不自动提示
* @param vm Vue对象(用于异常时自动toast提示异常信息)
* @return {Promise} Promise对象
*/

function http (option, vm) {
    return new Promise((resolve, reject) => {
        let method = option.method || 'POST'
        let url = baseUrl + option.url
        let timeout = option.timeout || 10000
        let headers = option.headers || {}
        let responseType = option.responseType
        let data = {} // 可以在此设置默认值
        if (option.data) {
            if (option.data instanceof FormData) {
                headers['Content-Type'] = 'multipart/form-data'
                let formData = option.data
                Object.keys(data).forEach((key) => {
                    formData.append(key, data[key])
                })
                data = formData
            } else {
                data = { ...data, ...option.data }
            }
        }

        let requestOptions = { method, url, headers, timeout, responseType }
        if (method.toUpperCase() === 'GET') {
            requestOptions.params = data
        } else {
            requestOptions.data = data
        }
        axios(requestOptions).then( (res) => {
            const contentDisposition = res.headers['content-disposition']
            // 文件下载
            if (contentDisposition &&
        (/filename\*=UTF-8''(.*)/.test(contentDisposition) || /filename="(.*)"/.test(contentDisposition))) { // 如果是文件下载
                const utf8Match = contentDisposition.match(/filename\*=UTF-8''(.*)/) // 匹配UTF-8的文件名
                const normalMatch = contentDisposition.match(/filename="(.*)"/) // 匹配普通英文文件名
                const filename = utf8Match ? decodeURIComponent(utf8Match[1]) : normalMatch[1]
                const blob = new Blob([res.data])
                const downloadElement = document.createElement('a')
                const href = window.URL.createObjectURL(blob)
                downloadElement.href = href
                downloadElement.download = filename
                document.body.appendChild(downloadElement)
                downloadElement.click()
                document.body.removeChild(downloadElement)
                window.URL.revokeObjectURL(href)
                resolve(res)
            } else { // JSON信息
                getResponseInfo(res).then((resInfo) => {
                    responseInfoHandle(resInfo, resolve, reject, option, vm, requestOptions)
                })
            }
        }, err => {
            errorhandle(err, reject, option, vm)
        }).catch(function (err) {
            errorhandle(err, reject, option, vm)
        })
    })

}

// 处理响应信息
function responseInfoHandle (resInfo, resolve, reject, option, vm) {
    // 请求是否成功
    let isSuccess = resInfo.retCode === '200'
    // 状态码
    let code = resInfo.retCode
    // 描述信息
    let message = resInfo.retMsg || '请求失败!'
    // 数据
    let resData = resInfo.data || {}
    if (isSuccess) { // 请求成功
        console.log(`[${option.method || 'POST'}]${option.url} 请求成功!\n请求参数:`, option.data, '\n响应结果:', resInfo)
        resolve(resData)
    } else { // 业务异常
        console.error(`[${option.method} || 'POST']${option.url} 请求失败!\n请求参数:`, option.data, '\n响应结果:', resInfo)
        let err = new BusinessError(code, message, resData)
        errorhandle(err, reject, option, vm)
    }
}

// 获取响应信息json对象

function getResponseInfo (res) {
    return new Promise((resolve, reject) => {
        // 返回的信息
        let resInfo = res.data
        if (resInfo instanceof Blob) {
            const reader = new FileReader()
            reader.readAsText(resInfo, 'utf-8')
            reader.onload = () => {
                resInfo = JSON.parse(reader.result)
                resolve(resInfo)
            }
        } else {
        resolve(resInfo)
        }
    })
}

/* 异常处理 */
function errorhandle (err, reject, option, vm) {
    let error = null
    if (err.name === 'BusinessError') {
        error = err
    } else {
        console.error(option.url, '请求失败!', err.code, err)
        error = new SystemError(500, '非常抱歉,系统出现错误,请稍后重试!')
    }
    console.log('error = ', error)
    if (vm) {
        if (error.name === 'BusinessError') { // 业务异常
            // 没有权限
            if (error.code === 'xxx') {
                error.ignore = true
                if (!isShowUnauthorized) {
                    vm.$popupAlert({
                        title: '提示',
                        message: '未登录或者会话已过期,请重新登录!',
                        width: 330,
                        height: 180,
                        btnText: '重新登录',
                        onOK: () => {
                            isShowUnauthorized = false // 是否显示重新登录弹框设为true
                            // 跳转到登录页面,登录成功后还跳转到原路径
                            vm.$router.push({ name: 'login', params: { fromPath: vm.$route.fullPath } })
                            vm.$eventBus.$emit('NO_AUTH_EVENT')
                        }
                    })
                    isShowUnauthorized = true // 是否显示重新登录弹框设为true
                }
                error.ignore = true
            } else if (option.toastError !== false) {
                vm.$toast({ type: 'error', message: error.message })
            }
        } else { // 系统异常
            vm.$toast('网络异常!')
        }
    }
    reject(error)
}

export default {
    baseUrl,
    http,
    post,
    get,
    download
}

apiPlugin.js,封装成plugin插件

import Vue from 'vue'
import api from '@/assets/js/api.js'

export default {
    install () {
        Vue.prototype.$api = api
    }
}

main.js,注入插件

import ApiPlugin from './plugins/apiPlugin.js'

// 后台接口插件
Vue.use(ApiPlugin)

4、使用事例

4.1下载

this.$api.download({
    url: '/xxx/xxx/xxx',
    data: params
}, this)

4.2get

this.$api.get({
    url: `/xxx/xxx/xx`,
    data: params
}, this).then((res) => {
    console.log(res)
})

4.3post

this.$api.post({
    url: '/api/basicList/query',
    data: params
}, this).then(res => {
})

到这里axios的封装基本就完成了

到此这篇关于在Vue中是如何封装axios的文章就介绍到这了,更多相关在Vue中封装axios内容请搜索猪先飞以前的文章或继续浏览下面的相关文章希望大家以后多多支持猪先飞!

[!--infotagslink--]

相关文章

  • vue中activated的用法

    这篇文章主要介绍了vue中activated的用法,帮助大家更好的理解和使用vue框架,感兴趣的朋友可以了解下...2021-01-03
  • 基于vue-simple-uploader封装文件分片上传、秒传及断点续传的全局上传插件功能

    这篇文章主要介绍了基于vue-simple-uploader封装文件分片上传、秒传及断点续传的全局上传插件,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-02-23
  • Vue基于localStorage存储信息代码实例

    这篇文章主要介绍了Vue基于localStorage存储信息代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-11-16
  • vue 监听 Treeselect 选择项的改变操作

    这篇文章主要介绍了vue 监听 Treeselect 选择项的改变操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-09-01
  • Antd-vue Table组件添加Click事件,实现点击某行数据教程

    这篇文章主要介绍了Antd-vue Table组件添加Click事件,实现点击某行数据教程,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-11-17
  • vue 实现动态路由的方法

    这篇文章主要介绍了vue 实现动态路由的方法,文中示例代码非常详细,帮助大家更好的理解和学习,感兴趣的朋友可以了解下...2020-07-06
  • Vue组件跨层级获取组件操作

    这篇文章主要介绍了Vue组件跨层级获取组件操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-07-28
  • vue treeselect获取当前选中项的label实例

    这篇文章主要介绍了vue treeselect获取当前选中项的label实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-09-01
  • vue 获取到数据但却渲染不到页面上的解决方法

    这篇文章主要介绍了vue 获取到数据但却渲染不到页面上的解决方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-11-19
  • Vue中slot-scope的深入理解(适合初学者)

    这篇文章主要给大家介绍了关于Vue中slot-scope的深入理解,这个教程非常适合初学者,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-04-17
  • vuejs element table 表格添加行,修改,单独删除行,批量删除行操作

    这篇文章主要介绍了vuejs element table 表格添加行,修改,单独删除行,批量删除行操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-07-18
  • antdesign-vue结合sortablejs实现两个table相互拖拽排序功能

    这篇文章主要介绍了antdesign-vue结合sortablejs实现两个table相互拖拽排序功能,本文通过实例图文相结合给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-01-09
  • vue项目多环境配置(.env)的实现

    最常见的多环境配置,就是开发环境配置,和生产环境配置,本文主要介绍了vue项目多环境配置的实现,感兴趣的可以了解一下...2021-07-20
  • Vue 3.0中jsx语法的使用

    这篇文章主要介绍了Vue 3.0 中 jsx 语法使用,帮助大家更好的理解和使用vue框架,感兴趣的朋友可以了解下...2020-11-13
  • vue项目页面嵌入代码块vue-prism-editor的实现

    这篇文章主要介绍了vue项目页面嵌入代码块vue-prism-editor的实现,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2020-10-30
  • vue Treeselect下拉树只能选择第N级元素实现代码

    这篇文章主要介绍了vue Treeselect下拉树只能选择第N级元素实现代码,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-09-01
  • vue实现同时设置多个倒计时

    这篇文章主要为大家详细介绍了vue实现同时设置多个倒计时,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-05-20
  • Ant design vue table 单击行选中 勾选checkbox教程

    这篇文章主要介绍了Ant design vue table 单击行选中 勾选checkbox教程,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-10-25
  • 解决vue的router组件component在import时不能使用变量问题

    这篇文章主要介绍了解决vue的router组件component在import时不能使用变量问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-07-27
  • vue实现div单选多选功能

    这篇文章主要为大家详细介绍了vue实现div单选多选功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-07-16