Аксиомы рационального распределения Vue и практическое применение в проекте 😀

Vue.js
Аксиомы рационального распределения Vue и практическое применение в проекте 😀

Подари розы, аромат в твоих руках, какой ты, какой твой мир💡

предисловие

В этой статье объясняются некоторые аспекты инкапсуляции и применения аксиом в проекте Заинтересованные разработчики могут прочитать эту статью.

Установить зависимости

  • установка аксиом
    # yarn | npm安装
    yarn add axios | npm install axios
  • использование аксиом
import axios from "axios";

axios.post("url",{}).then((res) => {
  // 接口调用成功回调
}).catch((error) => {
  // 接口调用失败毁掉
});

/*
    支持所有http请求以及请求取消、并发请求等功能,更多细节以及使用方法移步官方文档
    文档: [axios文档](http://www.axios-js.com/zh-cn/docs/)
*/

настроить аксиомы

Затем вернемся к теме этой статьи, как разумно настроить ее, чтобы повысить эффективность разработки и удобство сопровождения.

  • Чтобы создать файл конфигурации, мы просто немного инкапсулируем axios, поэтому создайте папку конфигурации в src и создайте ее в каталоге конфигурации.axios.jsдокумент

  • Упакованный код конфигурации axios выглядит следующим образом, поместите следующий код вaxios.jsв файле.

/**
 * 对axios稍作封装
 * 1. 设置请求超时时间
 * 2. 添加请求拦截器,在每个请求的头部添加token
 * 3. 添加响应拦截器,根据服务器返回状态进行相应的结果返回
*/
"use strict";
import axiosObj from "axios";
// 导入vuex,需要获取里面存储的token,请求时带上token,如果不需要可以不用导入
import store from "../store";
const defaultConfig = {
 // baseURL在此处省略配置,考虑到项目可能由多人协作完成开发,域名也各不相同,此处通过对api的抽离,域名单独配置在base.js中

 // 请求超时时间
 timeout: 60 * 1000,
 // 跨域请求时是否需要凭证
 // withCredentials: true, // Check cross-site Access-Control
 heards: {
   get: {
     // 设置默认请求头,当需要特殊请求头时,将其作为参数传入,即可覆盖此处的默认参数
     "Content-Type": "application/x-www-form-urlencoded;charset=utf-8"
   },
   post: {
     // 设置默认请求头,当需要特殊请求头时,将其作为参数传入,即可覆盖此处的默认参数(第三个参数即config)
     // 例如:
     //     services.post(`${base.lkBaseURL}/uploads/singleFileUpload`, file, {
     //       headers: { "Content-Type": "multipart/form-data" }
     //     });
     "Content-Type": "application/json;charset=utf-8"
    }
  }
 // 在向服务器发送请求前,对数据进行处理,axios默认会序列化数据
 // transformRequest:[function(data){
 //
 // }],
 // 在传递给 then/catch 前,修改响应数据
 // transformResponse:[function(data){
 //
 // }]
 };
/**
 * 请求失败后的错误统一处理,当然还有更多状态码判断,根据自己业务需求去扩展即可
 * @param status 请求失败的状态码
 * @param msg 错误信息
*/
const errorHandle = (status: number, msg: string) => {
 // 状态码判断
 switch (status) {
   // 401: 未登录状态,跳转登录页
   case 401:
     // 跳转登录页
     break;
   // 403 token过期
   case 403:
     // 如果不需要自动刷新token,可以在这里移除本地存储中的token,跳转登录页

     break;
   // 404请求不存在
   case 404:
     // 提示资源不存在
     break;
   default:
     console.log(msg);
  }
};

// 创建实例
const _axios = axiosObj.create(defaultConfig);
// 请求拦截器
_axios.interceptors.request.use(
 function(config) {
   // 从vuex里获取token
   const token = store.state.token;
   // 如果token存在就在请求头里添加
   token && (config.headers.token = token);
   return config;
 },
 function(error) {
   // Do something with request error
   error.data = {};
   error.data.msg = "服务器异常";
   return Promise.reject(error);
 }
);

// 响应拦截器
_axios.interceptors.response.use(
 function(response) {
   // 清除本地存储中的token,如果需要刷新token,在这里通过旧的token跟服务器换新token,将新的token设置的vuex中
   if (response.data?.code === 401) {
     localStorage.removeItem("token");
     // 页面刷新
     parent.location.reload();
   }
   if (response.status === 200) {
     // 处理接口中的data
     if (response.data?.data) {
       try {
         const dataObj = JSON.parse(response.data.data);
         if (typeof dataObj == "object" && dataObj) {
           // 为json字符串将其转为json对象
           response.data.data = dataObj;
         }
       } catch (e) {
         // 不是json字符串就不处理
         return response.data;
       }
     }
     return response.data;
   }
   response.data.code = -1;
   response.data.msg = "服务器错误";
   return response;
 },
 function(error) {
    if (error) {
      // 请求已发出,但不在2xx范围内
      errorHandle(error.status, error.data.msg);
      return Promise.reject(error);
    } else {
      // 断网
      return Promise.reject(error);
    }
  }
);
export default _axios;

После выполнения вышеуказанных шагов базовая конфигурация axios завершена.Давайте посмотрим, что сделала приведенная выше конфигурация.

  • установить тайм-аут
  • Централизованная настройка заголовков запросов
  • Унифицированная обработка кода состояния после сбоя ответа
  • Добавить токен для запроса перехвата
  • Обрабатывать истечение срока действия токена и возвращать данные соответственно при перехвате ответа
  • Извлечение доменного имени интерфейса
  • Наконец, экспортируйте его, мы будем использовать его при извлечении API.

Извлечь API и интерфейс доменного имени

Зачем делать извлечение API? Предположим, что все наши запросы написаны в бизнес-кодеthis.$axios.get(), более поздние изменения интерфейса, есть новые требования для передачи большего количества параметров в прошлом, мы должны перейти к бизнес-коду, чтобы найти и изменить их один за другим, ремонтопригодность отсутствует вообще. Далее я поведу вас к достижению разделения API 😃

Реализовать идеи

Мы улучшим ремонтопригодность интерфейса проекта, выполнив следующие шаги:

  1. Создайте файл модуля интерфейса, запишите здесь конкретный адрес интерфейса, параметры, метод запроса и т. д. и, наконец, экспортируйте его, чтобы упростить ссылку на файл унифицированного экспорта API.
  2. Создайте файл имени домена интерфейса. В команде может быть несколько имен доменов интерфейса. Мы записываем его здесь и, наконец, экспортируем для удобства использования в файле модуля интерфейса.
  3. Создайте единый файл экспорта API и разделите интерфейс API на несколько модулей в соответствии с функциями (шаг 1), что способствует разработке несколькими людьми.Назначьте руководителя модуля в команде, внесите все модули здесь, выставьте ссылки, а затем подключите их к прототипу Vue.this.$api.modulename.methodnameЦитировать.

код реализации

  • Создайте папку API в src
  • Создайте файл доменного имени интерфейсаindex.js
    /*
   * 接口域名管理
   *
   * */
   const base = {
       lk:"https://www.kaisir.cn/user",
       other:"https://kf.kaisir.cn/api"
   };
   
   export default base;
  • существуетapiСоздайте в папке файл модуля интерфейса и назовите его следующим образом:模块名+API.
    /*
    * 网站管理接口
    * */
    import services from '../plugins/axios'
    import base from './base'; // 导入接口域名列表
    const websiteManageAPI = {
        // 登录
        login(params){
            return services._axios.post(`${base.lk}/login`,params);
        },
        // 测试post接口
        postJSON(params){
            return services._axios.post(`${base.lk}/getter/postJSON`,params);
        },
        // 测试get接口
        getJSON(pageNo,pageSize){
            return services._axios.get(`${base.lk}/getter/getJSON`,{params:{pageNo:pageNo,pageSize:pageSize}});
        }
    };
    
    export default websiteManageAPI;
  • Создать унифицированный файл экспорта API
   /**
    * api统一出口
    * */
   // 网站管理接口
   import websiteManageAPI from './websiteManageAPI';
   // 其他模块接口
   
   // 导出接口
   export default {
       websiteManageAPI,
       // ...
   }

После выполнения вышеуказанных шагов содержимое в папке API выглядит следующим образом.

Далее мы можем выбратьapi统一出口То, что показывает файл, монтируется в прототип. Или выберите загрузку по запросу и импортируйте любой модуль, используемый в бизнес-коде.

Здесь мы представляем, как смонтировать его в прототип, в файле вводаmian.jsДобавьте в него следующий код.

// 挂载到原型(main.js)
Vue.prototype.$api = api;

Адаптировать к Vue3

При использовании в vue3 идея инкапсуляции основного тела не изменилась.Если в проекте используется TypeScript, то в конфигурационном файле axios будет больше объявлений типов.Если вам нужно смонтировать апи к прототипу, вам нужно объявить его в файле конфигурации axios. файл.apiДля объявления типа запись монтирования в main.js должна быть изменена наapp.config.globalProperties.$api = api;.

20 октября 2020 г. я провел рефакторинг предыдущего проекта с помощью Vue 3. Адрес кода конфигурации axios, применимого к Vue 3, выглядит следующим образом:

папка апи:src/api

конфигурационный файл аксиос:config/axios.ts

файл объявления типа vue:src/shims-vue.d.ts

Разработчики, заинтересованные в рефакторинге проектов Vue2 с помощью Vue3, могут перейти на:Рефакторинг проекта Vue2 с помощью Vue3

практическое применение

Например, в таком сценарии: все интерфейсы на бэкенде должны быть авторизованы, а затем доступ осуществляется на основе токена, возвращаемого при успешном входе в систему. Внутренний интерфейс использует shiro+jwt для реализации аутентификации интерфейса и выдачи токена.

  • Когда страница загрузится, получите токен из локального хранилища
    // App.vue,created生命周期
    const token = localStorage.getItem("token");
  • Определить, существует ли токен, если нет, получить его
    // 
    if(lodash.isEmpty(token)){
        // 跳转登录页:此处仅用于演示,用户名和密码为固定数据,实际需求为跳转登录页面进行授权
        const userInfo = {
          "username":"测试",
          "password":"0x89oikklsa"
        };
        // 调用登录api
        this.$api.websiteManageAPI.login(userInfo).then((res)=>{
          // 将token进行存储并更新到vuex中
          localStorage.setItem("token",res.token);
          this.$store.state.token = res.token;
        });
    }else{
        // 更新vuex中的token
        this.$store.state.token = token;
    }
  • Результаты
  • Вызовите другие интерфейсы, чтобы проверить, успешно ли добавлен токен заголовка запроса.
    // 测试其他接口能否调用成功
    this.$api.websiteManageAPI.getJSON(1,3).then((res)=>{
        console.log("接口调用成功");
        console.log(res)
    });
}
  • Результаты

напиши в конце

  • Если в статье есть ошибки, исправьте их в комментариях, если статья вам поможет, ставьте лайк и подписывайтесь 😊
  • Эта статья была впервые опубликована в Наггетс, если вам нужно перепечатать, пожалуйста, оставьте сообщение в области комментариев 💌