[項目篇]vue3+ts 封裝request請求,storage緩存,config請求信息抽離 - 次日

這是我參與更文挑戰的第18天,活動詳情查看:更文挑戰前端

封裝request和config請求信息抽離處理

  1. 先安裝axios,畢竟請求是基於axios的。

npm: npm install axiosvue

yarn: yarn add axiosreact

image.png

  1. 在src的同級目錄下,建立shims-axios.d.ts。用於作axios的ts聲明

image.png

import { AxiosInstance, AxiosRequestConfig, AxiosPromise } from "axios"
/**
 * 自定義擴展axios模塊
 * @author 何小玍。
 */
declare module "axios" {
  export interface AxiosRequestConfig {
    /**
     * @description 設置爲true,則會在請求過程當中顯示loading動畫,直到請求結束才消失
     */
    loading?: boolean
    isDialog?: boolean
  }
  export interface AxiosInstance {
    <T = any>(config: AxiosRequestConfig): Promise<T>
    request<T = any>(config: AxiosRequestConfig): Promise<T>
    get<T = any>(url: string, config?: AxiosRequestConfig): Promise<T>
    delete<T = any>(url: string, config?: AxiosRequestConfig): Promise<T>
    head<T = any>(url: string, config?: AxiosRequestConfig): Promise<T>
    post<T = any>(
      url: string,
      data?: any,
      config?: AxiosRequestConfig
    ): Promise<T>
    put<T = any>(
      url: string,
      data?: any,
      config?: AxiosRequestConfig
    ): Promise<T>
    patch<T = any>(
      url: string,
      data?: any,
      config?: AxiosRequestConfig
    ): Promise<T>
  }
}
複製代碼
  1. src文件夾下,建立utils文件夾,放封裝文件request.js
/**
 * @description [ axios 請求封裝]
 */
// import store from "@/store";
import axios, { AxiosResponse, AxiosRequestConfig } from "axios";
// import { Message, Modal } from 'view-design' // UI組件庫
import { Dialog, Toast } from "vant";
import router from "@/router";
// 根據環境不一樣引入不一樣api地址
import { config } from "@/config";
const service = axios.create({
  baseURL: config.baseApi + "/api", // url = base url + request url
  timeout: 5000,
  withCredentials: false // send cookies when cross-domain requests
  // headers: {
  // 	// clear cors
  // 	'Cache-Control': 'no-cache',
  // 	Pragma: 'no-cache'
  // }
})
// Request interceptors
service.interceptors.request.use(
  (config: AxiosRequestConfig) => {
    // 加載動畫
    if (config.loading) {
      Toast.loading({
        message: "加載中...",
        forbidClick: true
      });
    }
    // 在此處添加請求頭等,如添加 token
    // if (store.state.token) {
    // config.headers['Authorization'] = `Bearer ${store.state.token}`
    // }
    return config;
  },
  (error: any) => {
    Promise.reject(error);
  }
)
// Response interceptors
service.interceptors.response.use(
  async (response: AxiosResponse) => {
    // await new Promise(resovle => setTimeout(resovle, 3000))
    Toast.clear();
    const res = response.data;
    if (res.code !== 0) {
      // token 過時
      if (res.code === 401)
        // 警告提示窗
        return;
      if (res.code == 403) {
        Dialog.alert({
          title: "警告",
          message: res.msg
        }).then(() => {})
        return
      }
      // 若後臺返回錯誤值,此處返回對應錯誤對象,下面 error 就會接收
      return Promise.reject(new Error(res.msg || "Error"))
    }
    // 注意返回值
    else return response.data
  },
  (error: any) => {
    Toast.clear();
    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 {
      if (error.message == "Network Error") error.message == "網絡異常,請檢查後重試!"
      error.message = "鏈接到服務器失敗,請聯繫管理員"
    }
    Toast(error.message)
    // store.auth.clearAuth()
    // store.dispatch("clearAuth")
    return Promise.reject(error)
  }
)
export default service
複製代碼
  1. src文件夾下面,建立config文件夾,放index.ts
export interface IConfig {
    env: string // 開發環境
    mock?: boolean // mock數據
    title: string // 項目title
    baseUrl?: string // 項目地址
    baseApi?: string // api請求地址
    APPID?: string // 公衆號appId  通常放在服務器端
    APPSECRET?: string // 公衆號appScript 通常放在服務器端
}

const dev: IConfig = {
    env: "development",
    mock: false,
    title: "開發",
    baseUrl: "http://localhost:8001", // 項目地址
    baseApi: "https://baidu.com/api", // 本地api請求地址,注意:若是你使用了代理,請設置成'/'
    APPID: "wx123456778890",
    APPSECRET: "xxx"
}

const prod: IConfig = {
    env: "production",
    mock: false,
    title: "生產",
    baseUrl: "https://www.xxx.com/", // 正式項目地址
    baseApi: "https://www.baidu.com/api", // 正式api請求地址
    APPID: "wx1234567890",
    APPSECRET: "xxx"
}

export const config: IConfig = import.meta.env.MODE == 'development' ? dev : prod
複製代碼
  1. 配置.env.development.env.production文件

在根目錄下,建立.env.development.env.production文件ios

.env.development

NODE_ENV='development'
# must start with VUE_APP_ 
VUE_APP_ENV = 'development'
OUTPUT_DIR = 'test'
複製代碼

.env.production

NODE_ENV='production'
# must start with VUE_APP_
VUE_APP_ENV = 'production'
OUTPUT_DIR = 'dist'
複製代碼
  1. 配置package.json文件

在scripts裏面,修改爲...web

根據不同的命令,走不一樣的config接口面試

"scripts": {
    "dev": "vite",
    "build": "vue-tsc --noEmit && vite build",
    "prod": "cross-env NODE_ENV=dev vue-cli-service serve --mode production",
    "lint": "vue-cli-service lint --mode development"
  }
複製代碼

至此 request的封裝和config請求信息抽離已經完成vuex

dev環境和prod環境也已經處理完成vue-cli

封裝storage文件

utils裏面建立storage.ts文件, 放置storage文件typescript

/**
 * 封裝操做localstorage本地存儲的方法
 */
export const storage = {
  //存儲
  set(key: string, value: any) {
    localStorage.setItem(key, JSON.stringify(value))
  },
  //取出數據
  get<T>(key: string) {
    const value = localStorage.getItem(key)
    if (value && value != "undefined" && value != "null") {
      return <T>JSON.parse(value)
    }
  },
  // 刪除數據
  remove(key: string) {
    localStorage.removeItem(key)
  }
};

/**
 * 封裝操做sessionStorage本地存儲的方法
 */
export const sessionStorage = {
  //存儲
  set(key: string, value: any) {
    window.sessionStorage.setItem(key, JSON.stringify(value))
  },
  //取出數據
  get<T>(key: string) {
    const value = window.sessionStorage.getItem(key)
    if (value && value != "undefined" && value != "null") {
      return JSON.parse(value)
    }
    return null
  },
  // 刪除數據
  remove(key: string) {
    window.sessionStorage.removeItem(key)
  }
}
複製代碼

搞掂收工,有不懂的儘管問,我有空就會回覆的啦npm

大佬們,感興趣能夠關注我公衆號鴨,如今仍是個位數呢,委屈屈...

人懶,不想配圖,望能幫到你們

公衆號:小何成長,佛系更文,都是本身曾經踩過的坑或者是學到的東西

有興趣的小夥伴歡迎關注我哦,我是:何小玍。 你們一塊兒進步鴨

記敘文:

技術文

亂七八糟系列

vue系列

typescript系列

react-native系列

相關文章
相關標籤/搜索