Vue + TypeScript + VueCli3+ 封装 axios 请求 并 解决跨域问题

一、版本说明

"vue": "^2.6.10",
"axios": "^0.19.0",
"@vue/cli-plugin-babel": "^4.0.0",
"@vue/cli-plugin-router": "^4.0.0",
"@vue/cli-plugin-typescript": "^4.0.0",
"@vue/cli-plugin-vuex": "^4.0.0",
"@vue/cli-service": "^4.0.0",
"vue-loader": "^15.7.1",
"vue-router": "^3.1.3",
 
"node": 10.13.0,     // cmd命令窗输入:node -v
"npm": 6.10.3,       // cmd命令窗输入:npm -v
"typescript": 3.7.4  // cmd命令窗输入:tsc -v

 

 


二、在 vue-cli3+ 版本下构建项目,也是使用 proxy 配置跨域代理

      首先在项目的根目录下,新建 vue.config.js 文件,主要内容如下

module.exports = {
    devServer: {
        open: true, // auto open brower 项目启动后自动打开浏览器...
        disableHostCheck: false,
        host: "0.0.0.0",
        port: 8099, // 修改端口号
        https: false,
        hotOnly: false, // See https://github.com/vuejs/vue-cli/blob/dev/docs/cli-service.md#configuring-proxy
        proxy: {     // string | Object 解决跨域问题
            '/api': {
                target: 'http://xxxxxx:xxx', // 对应自己的 跨域地址 即请求的后端地址
                changeOrigin: true,
                ws: true,
                pathRewrite: {
                    '^/api': ''
                }
            }
        }
    }
};

 

 


三、 封装 axios 的 request.ts 文件,UI组件库( view-design )参考这里

       3.1、在 src\utils\ 目录下新建 request.ts 文件

       3.2、注意 axios 对象中,属性 baseURL 设置为 '/api'( 这里容易踩坑,因为在我把配置跨域代理、封装axios请求等之后,请求接口时,告诉我接口找不到,最开始我写的 `baseURL: '/'`,所以跨域代理配置的 '/api', 在此处就需要一致,即设置 `baseURL: '/api'` )   

                

 

/**
 * @description [ axios 请求封装]
 */
import axios from 'axios'
import { Message, Modal } from 'view-design' // UI组件库
import router from '../router'

const service = axios.create({
    baseURL: '/api', // url = base url + request url
    timeout: 5000,
    withCredentials: true,  // send cookies when cross-domain requests
    headers: {
        // clear cors
        'Cache-Control': 'no-cache',
        'Pragma': 'no-cache'
    }
})

// Request interceptors
service.interceptors.request.use(
    (config : any) => {
        // Add Authorization header to every request, you can add other custom headers here
        // 在此处添加请求头等,如添加 token
        // config.headers['Authorization'] = 'tokentokentokentokentokentokenhhh'
        return config
    },
    (error : any) => {
        Promise.reject(error)
    }
)

// Response interceptors
service.interceptors.response.use(
    (response : any) => {
        const res = response.data
        if (res.status !== 200) {
            (Message as any).error({
                content: res.info || 'Error',
                duration: 5,
                background: true
            })

            if (res.status === 401 || res.status === 403 || res.status === 408) {
                // 警告提示窗
                (Modal as any).warning({
                    // Modal.confirm({
                    title: '提示',
                    content: `你已被登出,可以取消继续留在该页面,或者重新登录`,
                    okText: '确定',
                    cancalText: '取消',
                    width: 300,
                    onOk: () => {
                        setTimeout(() => {
                            (Modal as any).remove();
                            (Modal as any).info('退出成功');
                            // 可在此处清空token等操作
                            router.push('/') // 跳转到登录页,具体根据项目路由修改
                        }, 2000)
                    }
                })
            }            
            // 若后台返回错误值,此处返回对应错误对象,下面 error 就会接收
            return Promise.reject(new Error(res.info || 'Error'))
        } else {
            // 注意返回值
            return response.data
        }        
    },
    (error : any) => {
        if (error && error.response) {
            switch (error.response.status) {
                case 400: error.message = '请求错误(400)'; break;
                case 401: error.message = '未授权,请登录(401)'; break;
                case 403: error.message = '拒绝访问(403)'; break;
                case 404: error.message = `请求地址出错: ${error.response.config.url}`; break;
                case 405: error.message = '请求方法未允许(405)'; break;
                case 408: error.message = '请求超时(408)'; break;
                case 500: error.message = '服务器内部错误(500)'; break;
                case 501: error.message = '服务未实现(501)'; break;
                case 502: error.message = '网络错误(502)'; break;
                case 503: error.message = '服务不可用(503)'; break;
                case 504: error.message = '网络超时(504)'; break;
                case 505: error.message = 'HTTP版本不受支持(505)'; break;
                default: error.message = `连接错误: ${error.message}`; 
            }
        } else {
            error.message = '连接到服务器失败,请联系管理员'
        }        
        (Message as any).error({
            content: error.info || error.message ||  'Error',
            duration: 5,
            background: true
        })
        return Promise.reject(error)
    }
)

export default service

 

 


四、组件中的使用,如 get 请求,请求接口时,直接写对应的接口地址即可,不用再添加 '/api'

以下是封装的 请求方法 getLists,组件中直接调用即可

Vue + TypeScript + VueCli3+ 封装 axios 请求 并 解决跨域问题_第1张图片

 

【获取成功】此时控制台显示接口虽然如下(本地拼接的路径),但其实Vue底层是将代理请求到 http://xxxxxx:xxx/userLIsts

Vue + TypeScript + VueCli3+ 封装 axios 请求 并 解决跨域问题_第2张图片

 

 

写给自己的随笔,有问题欢迎指出(Θ▽Θ)

 

 

 

 

 

 

 

你可能感兴趣的