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>

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,527评论 5 470
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,314评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,535评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,006评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,961评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,220评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,664评论 3 392
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,351评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,481评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,397评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,443评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,123评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,713评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,801评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,010评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,494评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,075评论 2 341

推荐阅读更多精彩内容