Vue项目使用Axios封装网络请求模块

4,215 阅读4分钟

「这是我参与2022首次更文挑战的第4天,活动详情查看:2022首次更文挑战

前言

在项目中网络请求模块是前后端沟通的基础,接下来我们就在Vue项目中使用Axios实现最基本的网络请求模块吧。

项目背景

  • Vue2
  • Vue-axios
  • axios PS:axios是一个库,它不是一个vue的第三方插件,所以无法像其他第三方插件一样直接使用Vue.use()来安装。
    为了更方便使用我们引入vue-axios(www.npmjs.com/package/vue…) ,作者介绍说vue-axios是将axios集成到Vue.js的小包装器,可以把axios像插件一样进行安装。

安装

npm install --save axios vue-axios

使用

import Vue from 'vue'

import axios from 'axios'

import VueAxios from 'vue-axios'

Vue.use(VueAxios, axios)

操作步骤

1.确定结构

image.png

在src目录下创建一个service的文件夹封装的通用网络请求的js代码写在下面

  • interceptors.service.js:axios拦截器 用来添加发送请求前和接收数据后需要做的事情。
  • api.service.js:用来封装不同类型请求的公共方法。

在src目录下创建一个apis的文件夹

  • 创建不同功能模块对应的api文件

2.拦截器 interceptors.service.js

利用Axios的拦截器方法interceptor.interceptors.request.use()发送request请求 之前做了一些配置:

  • 传入用户的token,发送给后端进行身份识别
  • 传入用户当前选择的语言,让后端可以根据当前语言输出相应的资料
  • 设置发出请求的loading动画

当然你也可以根据项目的具体需求做一些更详细的配置

import axios from "axios";
const interceptor = axios.create();

interceptor.interceptors.request.use(
  function(config) {
      //设置headers传入用户的token
    if (localStorage.id_token) {
      config.headers.Authorization = "Bearer " + localStorage.id_token;
    }
    //设置headers头传入当前使用的语言,提供给后端判断用。
    config.headers["Accept-Language"] = i18n.locale;
    
    //这边可以使用一些loading的动画,请求的时候loading动画运转,请求完成或者错误之后动画关闭
    //(这里用的是element-ui 的loading组件)
    loadingInstance = Loading.service({
      lock: true,
      background: "transparent"
    });

    return config;
  },
  function(error) {
    // 请求错误,关闭loading动画,返回错误。
    loadingInstance.close();
    return Promise.reject(error);
  }
);

* (ps:我这边传入当前语言是用的 vue-i18n 套件,想了解的可以看我这篇文章 Vue2项目中前端国际化处理 vue-i18n + element

利用Axios的拦截器方法interceptor.interceptors.response.use接收的response响应 进行判断和操作的处理

  • 请求成功,关闭loading动画 ,返回数据
  • 请求失败,关闭loading动画,和后端同学约定规则,抓取错误码,针对错误码进行判断和自定义错误之后如何处理。 常用的错误处理是页面alert错误信息,页面跳转。
    常见错误码:400-请求无效,404-无法找到网页,403-服务器端禁止访问,等等
interceptor.interceptors.response.use(
   //成功返回数据
  function(response) {
     //关闭loading动画
    loadingInstance.close();
    //返回数据待使用
    return response.data;
  },
  //抓取数据,针对不同的错误进行不同的操作
  function(error) {
     //和后端小伙伴约定一下错误码的规则
    if (error.response.status === 400) {
      switch (error.response.data.message) {
        case "Not found user":
        case "Unauthorized":
          // do nothing.
          break;
        case "Blocked":
          router.push({ path: "/inactive" });
          break;
        default:
          //页面输出错误讯息(element-ui)
          Message.error("Oop, something went wrong. Please contact us.");
      }
    }

    if (error.response.status === 403) {
      //页面输出错误讯息(element-ui)
      Message.error(error.response.data.message);
    }

    if (error.response.status === 404) {
      //跳转404页面
      router.push({
        name: "404"
      });
    }
    //关闭loading动画
    loadingInstance.close();

    return Promise.reject(error);
  }
);

最后导出模块

export default interceptor;

3.封装公共方法API api.service.js

常用的方法

  • get(resource, slug = "", params) :用于获取数据;
  • post(resource, params, config) :用于提交数据(新建),表单提交和文件上传等
  • patch(resource, params, config) ,put(resource, params, slug = ""):用于更新数据(修改);
  • delete(resource, params, config) :用于删除数据;
import Vue from "vue";
//引入刚刚的配置好的axios拦截器
import axios from "@/service/interceptors.service";
import VueAxios from "vue-axios";

const ApiService = {
  //初始化方法用vue-axios组件
  init() {
    Vue.use(VueAxios, axios);
    //设置api的baseURL
    Vue.axios.defaults.baseURL = "https://www.qq.com/api/";
  },
   
  //创建不同的网络请求方法
  get(resource, slug = "", params) {
    return Vue.axios.get(`${resource}/${slug}`, { params }).catch(error => {
      throw error.response;
    });
  },
  
  query(resource, params) {
    return Vue.axios.get(resource, { params }).catch(error => {
      throw error.response;
    });
  },

  post(resource, params, config) {
    return Vue.axios.post(`${resource}`, params, config).catch(error => {
      throw error.response;
    });
  },

  patch(resource, params, slug = "") {
    return Vue.axios.patch(`${resource}/${slug}`, params).catch(error => {
      throw error.response;
    });
  },

  put(resource, params, slug = "") {
    return Vue.axios.put(`${resource}/${slug}`, params).catch(error => {
      throw error.response;
    });
  },

  delete(resource, params, slug = "") {
    return Vue.axios
      .delete(`${resource}/${slug}`, { data: params })
      .catch(error => {
        throw error.response;
      });
  }
};

export default ApiService;

4. main.js引入封装好的网络请求模块

想要正常的使用,需要将封装好的网络请求模块引入

//main.js
import ApiService from "@/service/api.service";
ApiService.init();

5.根据不同功能模块的创建各自的API方法文件

比如关于学生的功能模块就创建一个@/apis/students.js,老师的功能模块就创建一个@/apis/teachers.js

image.png

引入api.service网络请求,新增api方法

*src/apis/students.js*
import ApiService from "@/common/api.service";
export default {
  getStudents() {
    return ApiService.query("students");
  }
}

将每个功能模块都单独创建一个api文件,编写只属于这个模块的api方法。
这样做的好处是: 小伙伴们看到这个api的文件名字就能很好的理解这个api是服务于哪一个功能模块的,更加方便小伙伴快速上手,减少沟通成本。如果之后某个模块的api需要调整的话可以快速定位对应的api文件,修改起来也很方便。

6.在组件中使用

引入该功能模块对应的api文件,在需要和后端对接的时候,调用api方法与后端做沟通。

*students.vue*
import StudentsApi from "@/apis/students.js";
export default {
  data() {
    return {
        students: null
    };
  },
  computed: {},
  watch: {},
  async mounted() {
    this.students = await StudentsApi.getStudents();
  },
  methods: {}
};
</script>

小结

以上就是我在项目中使用的网络请求模块的封装全部操作,希望可以给大家带来帮助Thanks♪(・ω・)ノ。