vue3.0+ts+axios封装+跨域

前些日子,做了一个vue的H5项目,前后端分离,采用的是vue3.0+ts+axios,过程中采了些坑,分享出来,希望能对遇到相似坑的码友有所帮助!

想了想还是从最基础的开始讲,照顾一些像我这样的小白,老鸟自行跳过;


一、环境安装

1.modeJs安装:

Node.js 安装包及源码下载地址为:https://nodejs.org/en/download/。下载完后傻瓜式安装就行;

2.安装vue3.0

打开Powershell或cmd命令工具执行 npm install -g @vue/cli


二、项目搭建

1. 选择自己的项目目录,执行 vue create 项目名

2. 下面是选择:

    ? Please pick a preset: Manually select features

    ? Check the features needed for your project: Choose Vue version, Babel, TS, Router, Vuex, CSS Pre-processors, Linter

    ? Choose a version of Vue.js that you want to start the project with 3.x

    ? Use class-style component syntax? No

    ? Use Babel alongside TypeScript (required for modern mode, auto-detected polyfills, transpiling JSX)? Yes

    ? Use history mode for router? (Requires proper server setup for index fallback in production) Yes

    ? Pick a CSS pre-processor (PostCSS, Autoprefixer and CSS Modules are supported by default): Sass/SCSS (with dart-sass)

    ? Pick a linter / formatter config: Basic

    ? Pick additional lint features: Lint on save

    ? Where do you prefer placing config for Babel, ESLint, etc.? In dedicated config files

    ? Save this as a preset for future projects? No

3. 可以看见,是没有vue.config.js的,我们需要手动在项目根目录下添加这个文件(PS:一定不要将扩展名写成.ts,这是血一样的教训,扩展名只能是.js

下面是我的配置:

module.exports = {

    devServer: {

        open: false, // 是否自动弹出浏览器页面    

        host: '0.0.0.0',

        port: '8080',

        https: false, // 是否使用https协议  

        hotOnly: true, // 是否开启热更新

        disableHostCheck: true,

        proxy: {

            '/api': {  //这个名字与 interceptors.ts 中的 baseURL 一定要一致,切记!

                target: '要请求的api基地址',

                changeOrigin: true,

                ws: true,

                pathRewrite: {

                    '^/api': ''

                }

            }

        }

    }

}


三、axios封装

1.先封装拦截器interceptors.ts

上代码:

import axios, { AxiosInstance } from "axios"

export class Interceptors {

    instance: AxiosInstance

    constructor() {

        this.instance = axios.create({

            baseURL: '/api',    //vue.config.js中的命名,上述说到了

            timeout: 10000,

        });

    }

    // 初始化拦截器

    init() {

        // 请求接口拦截器

        this.instance.interceptors.request.use(

            (config) => {

                // 判断一下是否有cookie 如果有的话则把cookie放入请求头中

                config.headers['Content-Type'] = 'application/x-www-form-urlencoded;charset=utf-8'

                return config

            },

            (err) => {

                console.error(err)

            }

        );

        // 响应拦截器

        this.instance.interceptors.response.use(

            (response) => {

                const result = response.data

                if (!response.status.toString().startsWith("2") || result.code === -1) {

                    // 如果状态码不是2开头或者接口code返回-1 则是返回错误信息

                    console.error("系统错误,请检查API是否正常!")

                    return

                }

                if (result.code !== 200) {

                    if (result.code === -3) {

                        console.error("登录过期")

                        //清除本地的token

                    } else {

                        if (result.msg) {

                            console.error(result.msg)

                        }

                    }

                    return Promise.resolve(result)

                } else {

                    // 返回成功则把token存储一下

                    return result

                }

            },

            (error) => {

                if (error.message === "Request failed with status code 500") {

                    console.error("系统错误,请检查API是否正常!")

                    return

                }

                let code = -110

                if (error && error.response && error.response.status) {

                    code = error.response.status

                    // 登录过期

                    if (code === 401 || code === -3) {

                        //清除本地token

                    }

                } else {

                    console.error(error.message)

                }

                const err = { errCode: -110, errMsg: error.message || "Error" }

                return Promise.resolve(err)

            }

        );

    }

    // 返回一下

    getInterceptors() {

        return this.instance

    }

}

2.我将发送请求封装在http.ts:

import { AxiosPromise, AxiosResponse } from "axios"

import { Interceptors } from "./interceptors"

// 请求配置

export class HttpServer {

    axios: any

    // 获取axios实例

    constructor() {

        this.axios = new Interceptors().getInterceptors()

    }

    // 简单封装一下方法

    request(config: any): AxiosPromise {

        return new Promise((resolve, reject) => {

            this.axios(config).then((result: AxiosResponse) => {

                resolve(result)

            }).catch((err: any) => {

                reject(err)

            })

        });

    }

}

const Http = HttpServer

export default Http

PS:加入我们要请求:http://www.baidu.com/register ,做跨域后现实的请求地址是 http://192.168.1.9:8080/api/register,虽然看上去还是本地地址,但实际是请求了http://www.baidu.com/register;


四、使用方式,这里我使用了async+await的方式,本人不喜欢then的风格,举个栗子,model.ts(模型层,从api中请求数据,返回给入口文件index.ts)、index.ts(模块入口,梳理接口数据并按需作逻辑处理):

1.model.ts:

import Http from '@/http'

import { Method } from 'axios';

export default class TestModel extends Http {

    registerModel(data: any): any{

        const url = '除去api基地址外的路径,如(http://www.baidu.com/register 只需写 '/register')'

        const param = {

            url,

            data,

            method: <Method>'POST'

        }

        return this.request(param)

    }

}

2.index.ts:

import UserModel from './model'

export default class UserServer extends UserModel {

register(data: any): any{

        return new Promise(async resolve => {

            const result = await this.registerModel(data)

            if (result) {

                //逻辑处理后

                resolve({ ...result }) 

            }

        })

    }

}

3.test.vue:

<template>

    <div>

        <div class="clum">

            <button @click="config">点击测试</button>

        </div>

    </div>

</template>

<script lang="ts">

/* 导入模块 */

import TestServer from '@/api/index'

/* 实例化模块 */

const server = new TestServer()

export default {

    name: 'test',

    data(){

        return {

        }

    },

    methods: {

        async register(){

            const result = await server.config()

            console.log(result)

        }

    }

};

</script>

以上就是我的经历,希望对你有用!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容