风姿曲 發表於 2021-10-27 11:08:00

使用typescript封装axios

<h2 id="使用typescript封装axios">使用typescript封装axios</h2>
<p>这个axios封装,因为是用在vue3的demo里面的,为了方便,在vue3的配置里面按需加载element-plus</p>
<h3 id="封装axios">封装axios</h3>
<ul>
<li>http.ts</li>
</ul>
<pre><code class="language-javascript">import axios, { InternalAxiosRequestConfig, AxiosRequestHeaders, AxiosResponse, AxiosError } 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)

    /* 请求拦截this.service.interceptors.request.use(config =&gt; config, error =&gt; Promise.reject(error))*/
    this.service.interceptors.request.use((config: InternalAxiosRequestConfig) =&gt; {
      /* 业务逻辑
      1. 开启全屏loading动画
      2. 数据加密config.data
      3. 请求头加上token,结合vuex或localstorage:
          if(store.getters.token) config.headers['x-token'] = store.getters.token
          else 重定向
      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: AxiosError) =&gt; {
       /* 请求错误
      1. 关闭全屏loading动画
      2. 重定向到错误页
      */
      loading.close()
      // 处理 HTTP 网络错误
      let msg = '';
      const status = error.response?.status; // HTTP响应状态码
      switch (status) {
      case 404:
          msg = '请求路径错误-404';
          break;
      case 500:
          msg = '服务端错误-500';
          break;
      default:
          msg = '请求错误';
      }
      ElMessage.error(msg);
      return Promise.reject(error);
    })


    /* 响应拦截   this.service.interceptors.response.use(response =&gt; response.data, error =&gt; Promise.reject(error))*/
    this.service.interceptors.response.use((response: AxiosResponse) =&gt; {
      /*
      1. 关闭全屏loading动画
      2. 数据解密
      3. 根据 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 =&gt; {
      loading.close()
      ElMessage.error('请求失败',)
      return Promise.reject(error)
    })
}
get&lt;T&gt;(url: string, params?: object, _object = {}): Promise&lt;IResponseData&lt;T&gt;&gt; {
    return this.service.get(url, { params, ..._object })
}
post&lt;T&gt;(url: string, params?: object, _object = {}): Promise&lt;IResponseData&lt;T&gt;&gt; {
    return this.service.post(url, params, _object)
}
put&lt;T&gt;(url: string, params?: object, _object = {}): Promise&lt;IResponseData&lt;T&gt;&gt; {
    return this.service.put(url, params, _object)
}
delete&lt;T&gt;(url: string, params?: any, _object = {}): Promise&lt;IResponseData&lt;T&gt;&gt; {
    return this.service.delete(url, { params, ..._object })
}
}

export default new Http(config)
</code></pre>
<ul>
<li>types/index.ts: 接口返回数据的类型定义</li>
</ul>
<pre><code class="language-javascript">export interface IResponseData&lt;T&gt; {
status: number;
message?:string;
data:T;
code: string;
}
</code></pre>
<h3 id="axios的使用">axios的使用</h3>
<ul>
<li>list.vue:<br>
<code>const { data } = await http.get&lt;IList&gt;('/goods/list', queryForm.value)   list.value = data.list</code></li>
</ul>
<pre><code class="language-html">&lt;template lang="pug"&gt;
//- 查询form
el-form(:inline="true" :model="queryForm" size="small" label-position="left")
el-form-item
    el-button(type="primary" @click="operate")
      | 新增
el-form-item(label="商品编号")
    el-input(v-model="queryForm._id")
el-form-item(label="商品名")
    el-input(v-model="queryForm.goodName")
el-form-item(label="数量")
    el-input(v-model="queryForm.count")
el-form-item(label="详情")
    el-input(v-model="queryForm.des")
el-form-item
    el-button(type="primary" @click="query")
      | 查询

//- 列表
el-table(:data="list" center size="mini")
el-table-column(prop="goodName" label="商品名")
el-table-column(prop="count" label="数量")
el-table-column(prop="des" label="详情")
el-table-column(label="操作")
    template(#default="props")
      el-button(type="primary" size="small" @click="operate(props.row)")
      | 编辑
      el-button(type="danger" size="small" @click="operate(props.row, true)")
      | 删除

//- 新增、编辑
el-drawer(v-model="detailShow" :title="editShow === true ? '编辑' : '新增'" direction="rtl")
el-form(:model="detailForm" size="small" label-width="80px" label-position="left")
    //- el-form-item(label="商品编号" required v-if="false")
    el-form-item(label="商品编号" required v-if="log(editShow)")
      el-input(v-model="detailForm._id" readonly)
    el-form-item(label="商品名" required)
      el-input(v-model="detailForm.goodName")
    el-form-item(label="数量")
      el-input(v-model="detailForm.count")
    el-form-item(label="详情")
      el-input(v-model="detailForm.des")
    el-form-item
      el-button(type="primary" size="small" @click="submit")
      | 确定
&lt;/template&gt;

&lt;script lang="ts"&gt;
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&lt;IGoodInfo[]&gt;([])

    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&lt;IList&gt;('/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: '操作成功',
      type: 'success',
      })
      query()
    }


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

    return {
      detailShow,
      editShow,
      list,
      queryForm,
      detailForm,
      query,
      operate,
      submit,
      log
    }
}
});
&lt;/script&gt;

</code></pre>
<ul>
<li>types/goods.ts</li>
</ul>
<pre><code class="language-typescript">export interface IGoodInfo {
_id: string;
goodName: string;
count: string;
des: string
}

export interface IList {
list: IGoodInfo[]
}
</code></pre><br><br>
来源:https://www.cnblogs.com/shine-lovely/p/15469625.html
頁: [1]
查看完整版本: 使用typescript封装axios