Detailed example of using typescript to encapsulate axios in Vue3

Detailed example of using typescript to encapsulate axios in Vue3

This axios package is used in the vue3 demo. For convenience, element-plus is loaded on demand in the vue3 configuration.

Encapsulating Axios

http.ts

import axios, { AxiosRequestConfig, AxiosRequestHeaders, AxiosResponse } from 'axios'
import { IResponseData } from '@/types'
import { ElMessage, ElLoading, ILoadingInstance } from 'element-plus'

type TAxiosOption = {
  baseURL: string;
  timeout: number;
}

const config = {
  baseURL: '/',
  timeout: 120000
}

let loading: ILoadingInstance;

class Http {
  //service: AxiosInstance;
  service;
  constructor(config: TAxiosOption) {
    this.service = axios.create(config)

    /* Request interception this.service.interceptors.request.use(config => config, error => Promise.reject(error))*/
    this.service.interceptors.request.use((config: AxiosRequestConfig) => {
      /* Business logic 1. Enable full-screen loading animation 2. Data encryption config.data
      3. Add token to the request header, combined with vuex or localstorage:
          if (store.getters.token) config.headers['x-token'] = store.getters.token
          else redirect 4. …
      */
      loading = ElLoading.service({
        lock: true,
        text: 'Loading',
        spinner: 'el-icon-loading',
        background: 'rgba(255, 255, 255, 0.7)',
      })

      if (localStorage.getItem('token')) {
        (config.headers as AxiosRequestHeaders).authorization = localStorage.getItem('token') as string
      }

      return config
    }, error => {
      /* Request error 1. Close full-screen loading animation 2. Redirect to error page */
      loading.close()
      return Promise.reject(error) // In order to catch the error message in the code})


    /* Response interception this.service.interceptors.response.use(response => response.data, error => Promise.reject(error))*/
    this.service.interceptors.response.use((response: AxiosResponse<any>) => {
      /* 
      1. Close the full-screen loading animation 2. Data decryption 3. Perform different error handling based on response.data.code 4. …
      */
      loading.close()

      const data = response.data
      const { code } = data

      if (code !== '000000') {
        ElMessage.error(data.message)
        return Promise.reject(data)
      }
      return response.data
    }, error => {
      loading.close()
      ElMessage.error('Request failed',)
      return Promise.reject(error)
    })
  }
  get<T>(url: string, params?: object, _object = {}): Promise<IResponseData<T>> {
    return this.service.get(url, { params, ..._object })
  }
  post<T>(url: string, params?: object, _object = {}): Promise<IResponseData<T>> {
    return this.service.post(url, params, _object)
  }
  put<T>(url: string, params?: object, _object = {}): Promise<IResponseData<T>> {
    return this.service.put(url, params, _object)
  }
  delete<T>(url: string, params?: any, _object = {}): Promise<IResponseData<T>> {
    return this.service.delete(url, { params, ..._object })
  }
}

export default new Http(config)

types/index.ts: Type definition of the data returned by the interface

export interface IResponseData<T> {
  status: number;
  message?:string;
  data:T;
  code: string;
}

Use of axios

list.vue:

const { data } = await http.get<IList>('/goods/list', queryForm.value) list.value = data.list

<template lang="pug">
//- Query form
el-form(:inline="true" :model="queryForm" size="small" label-position="left")
  el-form-item
    el-button(type="primary" @click="operate")
      | Add el-form-item(label="Product Number")
    el-input(v-model="queryForm._id")
  el-form-item(label="Product Name")
    el-input(v-model="queryForm.goodName")
  el-form-item(label="quantity")
    el-input(v-model="queryForm.count")
  el-form-item(label="Details")
    el-input(v-model="queryForm.des")
  el-form-item
    el-button(type="primary" @click="query")
      | Query //- List el-table(:data="list" center size="mini")
  el-table-column(prop="goodName" label="Product Name")
  el-table-column(prop="count" label="quantity")
  el-table-column(prop="des" label="Details")
  el-table-column(label="operation")
    template(#default="props")
      el-button(type="primary" size="small" @click="operate(props.row)")
        | Edit el-button(type="danger" size="small" @click="operate(props.row, true)")
        | Delete //- Add, edit el-drawer(v-model="detailShow" :title="editShow === true ? 'Edit' : 'Add'" direction="rtl")
  el-form(:model="detailForm" size="small" label-width="80px" label-position="left")
    //- el-form-item(label="Product Number" required v-if="false")
    el-form-item(label="Product Number" required v-if="log(editShow)")
      el-input(v-model="detailForm._id" readonly)
    el-form-item(label="Product Name" required) 
      el-input(v-model="detailForm.goodName")
    el-form-item(label="quantity")
      el-input(v-model="detailForm.count")
    el-form-item(label="Details")
      el-input(v-model="detailForm.des")
    el-form-item
      el-button(type="primary" size="small" @click="submit")
        | OK</template>

<script lang="ts">
import { defineComponent, reactive, ref } from 'vue';
import { ElMessage } from 'element-plus'
import { IGoodInfo, IList } from '@/types/goods'
import http from '@/http'

export default defineComponent({
  name: 'Home',
  setup() {
    const list = ref<IGoodInfo[]>([])

    const queryForm = ref({ goodName: '', count: '', _id: '', des: '' })
    const detailForm = ref({ goodName: '', count: '', _id: '', des: '' })
    const detailShow = ref(false)
    const editShow = ref(false)

    query()


   	async function query() {
      const { data } = await http.get<IList>('/goods/list', queryForm.value)
      list.value = data.list
    }

    async function operate(form?: IGoodInfo, flag?: true) {
      if (!form) {
        detailShow.value = true
        editShow.value = false
        detailForm.value = { goodName: '', count: '', _id: '', des: '' }
      } else if (!flag) {
        detailShow.value = true
        editShow.value = true
        detailForm.value = { ...form }
      } else {
        await http.delete('/goods/delete', { _id: form._id })
        query()
      }
    }

    async function submit() {
      if (detailForm.value._id) {
        await http.put('/goods/edit', detailForm.value)
      }else{
        await http.put('/goods/edit', detailForm.value)
      }

      detailShow.value = false
      ElMessage({
        message: 'Operation successful',
        type: 'success',
      })
      query()
    }


    function log(params:any) {
     console.log(params);
     return params
    }

    return {
      detailShow,
      editShow,
      list,
      queryForm,
      detailForm,
      query,
      operate,
      submit,
      log
    }
  }
});
</script>

types/goods.ts

export interface IGoodInfo {
  _id: string;
  goodName: string;
  count: string;
  des: string
}

export interface IList {
  list: IGoodInfo[]
}

This is the end of this article about using typescript to encapsulate axios. For more related typescript encapsulation content, please search for previous articles on 123WORDPRESS.COM or continue to browse the following related articles. I hope everyone will support 123WORDPRESS.COM in the future!

You may also be interested in:
  • Vue3 + TypeScript Development Summary
  • Practical record of Vue3 combined with TypeScript project development
  • How to use vue3+TypeScript+vue-router
  • Vue3 TypeScript implements useRequest details

<<:  Detailed explanation of the use of grid properties in CSS

>>:  HTML+CSS implementation code for rounded rectangle

Recommend

What are the new CSS :where and :is pseudo-class functions?

What are :is and :where? :is() and :where() are p...

Summary of knowledge points on using calculated properties in Vue

Computed properties Sometimes we put too much log...

Working principle and example analysis of Linux NFS mechanism

What is NFS? network file system A method or mech...

CocosCreator ScrollView optimization series: frame loading

Table of contents 1. Introduction 2. Analysis of ...

MySQL 5.7.18 winx64 installation and configuration method graphic tutorial

The installation of compressed packages has chang...

mysql 8.0.12 winx64 download and installation tutorial

MySQL 8.0.12 download and installation tutorial f...

Navicat connects to MySQL8.0.11 and an error 2059 occurs

mistake The following error occurs when connectin...

jQuery achieves large-screen scrolling playback effect

This article shares the specific code of jQuery t...

Detailed explanation of Vue project optimization and packaging

Table of contents Preface 1. Routing lazy loading...

Example of how to check the capacity of MySQL database table

This article introduces the command statements fo...

Solution to inconsistent display of cursor size in input box

The cursor size in the input box is inconsistent T...

Uniapp's experience in developing small programs

1. Create a new UI project First of all, our UI i...

vue2.x configuration from vue.config.js to project optimization

Table of contents Preface vue.config.js configura...

Example of using CSS3 to achieve shiny font effect when unlocking an Apple phone

0. Introduction August 18, 2016 Today, I noticed ...