1. 程式人生 > >工具模塊封裝(三)

工具模塊封裝(三)

接口模擬 組件 local 通過 __proto__ 中控 準備 image 比較

封裝 axios 模塊

封裝背景

使用axios發起一個請求是比較簡單的事情,但是axios沒有進行封裝復用,項目越來越大,會引起越來越多的代碼冗余,讓代碼變得越來越難維護。所以我們在這裏先對 axios 進行二次封裝,使項目中各個組件能夠復用請求,讓代碼變得更容易維護。

封裝要點

  • 統一 url 配置
  • 統一 api 請求
  • request (請求) 攔截器,例如:帶上token等,設置請求頭
  • response (響應) 攔截器,例如:統一錯誤處理,頁面重定向等
  • 根據需要,結合 Vuex 做全局的 loading 動畫,或者錯誤處理
  • 將 axios 封裝成 Vue 插件使用

文件結構

在 src 目錄下,新建一個 http 文件夾,用來存放 http 交互 api 代碼。

技術分享圖片

config.js:axios 默認配置,包含基礎路徑等信息。
axios.js:二次封裝 axios 模塊,包含攔截器等信息。
interface.js :請求接口匯總模塊,聚合模塊 API。
index.js:將 axios 封裝成插件,按插件方式引入。

config.js

技術分享圖片
export default {
  method: ‘get‘,
  // 基礎url前綴
  baseURL: ‘http://localhost:8080/‘,
  // 請求頭信息
  headers: {
    ‘Content-Type‘: ‘application/json;charset=UTF-8‘
  },
  // 參數
  data: {},
  // 設置超時時間
  timeout: 10000,
  // 攜帶憑證
  withCredentials: true,
  // 返回數據類型
  responseType: ‘json‘
}
技術分享圖片

axios.js

技術分享圖片
import axios from ‘axios‘;
import config from ‘./config‘;
import qs from ‘qs‘;
import Cookies from "js-cookie";
import router from ‘@/router‘

// 使用vuex做全局loading時使用
// import store from ‘@/store‘

export default function $axios(options) {
  return new Promise((resolve, reject) => {
    const instance = axios.create({
      baseURL: config.baseURL,
      headers: {},
      transformResponse: [function (data) {
      }]
    })

    // request 攔截器
    instance.interceptors.request.use(
      config => {
        let token = Cookies.get(‘token‘)
        // 1. 請求開始的時候可以結合 vuex 開啟全屏 loading 動畫
        // console.log(store.state.loading)
        // console.log(‘準備發送請求...‘)
        // 2. 帶上token
        if (token) {
          config.headers.accessToken = token
        } else {
          // 重定向到登錄頁面
          router.push(‘/login‘)
        }
        // 3. 根據請求方法,序列化傳來的參數,根據後端需求是否序列化
        if (config.method === ‘post‘) {
          if (config.data.__proto__ === FormData.prototype
            || config.url.endsWith(‘path‘)
            || config.url.endsWith(‘mark‘)
            || config.url.endsWith(‘patchs‘)
          ) {

          } else {
            config.data = qs.stringify(config.data)
          }
        }
        return config
      },

      error => {
        // 請求錯誤時
        console.log(‘request:‘, error)
        // 1. 判斷請求超時
        if (error.code === ‘ECONNABORTED‘ && error.message.indexOf(‘timeout‘) !== -1) {
          console.log(‘timeout請求超時‘)
          // return service.request(originalRequest);// 再重復請求一次
        }
        // 2. 需要重定向到錯誤頁面
        const errorInfo = error.response
        console.log(errorInfo)
        if (errorInfo) {
          error = errorInfo.data  // 頁面那邊catch的時候就能拿到詳細的錯誤信息,看最下邊的Promise.reject
          const errorStatus = errorInfo.status; // 404 403 500 ...
          router.push({
            path: `/error/${errorStatus}`
          })
        }
        return Promise.reject(error) // 在調用的那邊可以拿到(catch)你想返回的錯誤信息
      }
    )

    // response 攔截器
    instance.interceptors.response.use(
      response => {
        let data;
        // IE9時response.data是undefined,因此需要使用response.request.responseText(Stringify後的字符串)
        if (response.data == undefined) {
          data = JSON.parse(response.request.responseText)
        } else {
          data = response.data
        }

        // 根據返回的code值來做不同的處理
        switch (data.rc) {
          case 1:
            console.log(data.desc)
            break;
          case 0:
            store.commit(‘changeState‘)
            // console.log(‘登錄成功‘)
          default:
        }
        // 若不是正確的返回code,且已經登錄,就拋出錯誤
        // const err = new Error(data.desc)
        // err.data = data
        // err.response = response
        // throw err

        return data
      },
      err => {
        if (err && err.response) {
          switch (err.response.status) {
            case 400:
              err.message = ‘請求錯誤‘
              break
            case 401:
              err.message = ‘未授權,請登錄‘
              break
            case 403:
              err.message = ‘拒絕訪問‘
              break
            case 404:
              err.message = `請求地址出錯: ${err.response.config.url}`
              break
            case 408:
              err.message = ‘請求超時‘
              break
            case 500:
              err.message = ‘服務器內部錯誤‘
              break
            case 501:
              err.message = ‘服務未實現‘
              break
            case 502:
              err.message = ‘網關錯誤‘
              break
            case 503:
              err.message = ‘服務不可用‘
              break
            case 504:
              err.message = ‘網關超時‘
              break
            case 505:
              err.message = ‘HTTP版本不受支持‘
              break
            default:
          }
        }
        console.error(err)
        return Promise.reject(err) // 返回接口返回的錯誤信息
      }
    )

    // 請求處理
    instance(options).then(res => {
      resolve(res)
      return false
    }).catch(error => {
      reject(error)
    })
  })
}
技術分享圖片

interface.js

按 Ctrl+C 復制代碼 按 Ctrl+C 復制代碼

index.js

按 Ctrl+C 復制代碼 按 Ctrl+C 復制代碼

安裝 js-cookie

上面 axios.js 中,會用到 Cookie 獲取 token,所以需要把相關依賴安裝一下。

執行以下命令,安裝依賴包。

yarn add js-cookie

代碼實例

1.引入插件

在 main.js 中以 vue 插件的形式引入 axios,這樣在其他地方就可通過 this.$api 調用相關的接口了。

技術分享圖片

2.編寫接口

在 interface.js 中添加 login 接口。

技術分享圖片

3.調用接口

在登錄界面 Login.vue 中,添加一個登錄按鈕,點擊處理函數通過 axios 調用 login 接口返回數據。

成功返回之後,將 token 放入 Cookie 並跳轉到主頁。

技術分享圖片
<template>
  <div class="page">
    <h2>Login Page</h2>
    <el-button type="primary" @click="login()">登錄</el-button>
  </div>
</template>

<script>
  import mock from ‘@/mock/mock.js‘;
  import Cookies from "js-cookie";
  import router from ‘@/router‘
  export default {
    name: ‘Login‘,
    methods: {
      login() {
        this.$api.login().then(function(res) {
       alert(res.data.token) Cookies.set(‘token‘, res.data.token) // 放置token到Cookie router.push(‘/‘) // 登錄成功,跳轉到主頁 }).catch(function(res) { alert(res); }); } } } </script>
技術分享圖片

4.mock 接口

在 mock.js 中添加 login 接口進行攔截,返回一個 token。

技術分享圖片

啟動測試

瀏覽器訪問:http://localhost:8080/#/login,顯示登錄界面。

技術分享圖片

點擊登錄按鈕,首先彈出框,顯示返回的 token 信息。

技術分享圖片

點擊確定關掉彈出框後,跳轉到主頁。點擊用戶、菜單按鈕,接口調用正常。

技術分享圖片

封裝 mock 模塊

為了統一可以統一管理和集中控制數據模擬接口,我們對 mock 模塊進行了封裝,可以方便的定制模擬接口的統一開關和個體開關。

文件結構

在 mock 目錄下新建一個 index.js ,創建 modules 目錄並在裏面創建三個模塊 *.js 文件。

技術分享圖片

index.js:模擬接口模塊聚合文件

login.js:登錄相關的接口模擬

user.js:用戶相關的接口模擬

menu.js:菜單相關的接口模擬

index.js

按 Ctrl+C 復制代碼 按 Ctrl+C 復制代碼

login.js

按 Ctrl+C 復制代碼 按 Ctrl+C 復制代碼

user.js

按 Ctrl+C 復制代碼 按 Ctrl+C 復制代碼

menu.js

按 Ctrl+C 復制代碼 按 Ctrl+C 復制代碼

修改引入

Login.vue

技術分享圖片

Home.vue

技術分享圖片

啟動測試

瀏覽器訪問:http://localhost:8080/#/,按照先前流程走一遍,沒有問題。

技術分享圖片

原文出處:https://www.cnblogs.com/xifengxiaoma/
自己整理記錄。

工具模塊封裝(三)