解析vue中axios的封装请求(附步骤代码)

一、简介

axios 是一个轻量的http客户端,它基于 xmlhttprequest 服务来执行 http 请求,支持丰富的配置,支持 promise,支持浏览器端和 node.js 端。自vue2.0起,尤大大宣布取消对vue-resource 的官方推荐,转而推荐 axios。现在 axios 已经成为大部分 vue 开发者的首选。( 如果你还不熟悉 axios,可以在这里查看它的api。)【相关推荐:vue.js视频教程】

封装前,先来看下,不封装的情况下,一个实际项目中axios请求的样子。

大概是长这样:

axios('http://localhost:3000/data', {  method: 'GET',  timeout: 1000,  withCredentials: true,  headers: {    'Content-Type': 'application/json',    Authorization: 'xxx',  },  transformRequest: [function (data, headers) {    return data;  }],  // 其他请求配置...}).then((data) => {  // todo: 真正业务逻辑代码  console.log(data);}, (err) => {  if (err.response.status === 401) {  // handle authorization error  }  if (err.response.status === 403) {  // handle server forbidden error  }  // 其他错误处理.....  console.log(err);});

登录后复制

可以看到在这段代码中,页面代码逻辑只在第15行处,上方的一大块请求配置代码和下方一大块响应错误处理代码,几乎跟页面功能没有关系,而且每个请求中这些内容都差不多,甚至有的部分完全一样。

二、封装后

1.封装步骤

立即学习“前端免费学习笔记(深入)”;

封装的本质就是在待封装的内容外面添加各种东西,然后把它们作为一个新的整体呈现给使用者,以达到扩展和易用的目的。

封装 axios 要做的事情,就是把所有HTTP请求共用的配置,事先都在axios上配置好,预留好必要的参数和接口,然后把它作为新的axios返回。

目录结构如下(由Vue-cli 3.0 生成):

|–public/|–mock/|   |–db.json  # 我新建的接口模拟数据|–src/|   |–assets/|   |–components/|   |–router/|   |–store/|   |–views/|       |–Home.Vue|   |–App.vue|   |–main.js|   |–theme.styl|–package.json|…

2.封装目标

在 Home 页,发起 axios 请求时就像调用一个只有少量参数的方法一样简单,这样我就可以专注业务代码了。

1. 将 axios 封装到一个独立的文件

在src下创建 utils/http.js 文件

  cd src  mkdir utils  touch http.js

登录后复制引入 axios

  // src/utils/http.js  import axios from 'axios';

登录后复制创建一个类

  //src/utils/http.js  //...  class NewAxios {    }

登录后复制给不同环境配置不同请求地址

根据process.env.NODE_ENV 配置不同的 baseURL,使项目只需执行相应打包命令,就可以在不同环境中自动切换请求主机地址。

// src/utils/http.js//...const getBaseUrl = (env) => {  let base = {    production: '/',    development: 'http://localhost:3000',    test: 'http://localhost:3001',  }[env];  if (!base) {    base = '/';  }  return base;};class NewAxios {  constructor() {    this.baseURL = getBaseUrl(process.env.NODE_ENV);  }}

登录后复制配置超时时间

timeout属性,我一般设置10秒。

// src/utils/http.js//...class NewAxios {  constructor() {    //...    this.timeout = 10000;  }}

登录后复制配置允许携带凭证

widthCredentials属性设为true

// src/utils/http.js//...class NewAxios {  constructor() {    //...    this.withCredentials = true;  }}

登录后复制给这个类创建实例上的方法request

在 request 方法里,创建新的axios实例,接收请求配置参数,处理参数,添加配置,返回axios实例的请求结果(一个promise对象)。

你也可以不创建,直接使用默认导出的axios实例,然后把所有配置都放到它上面,不过这样一来整个项目就会共用一个axios实例。虽然大部分项目下这样够用没问题,但是有的项目中不同服务地址的请求和响应结构可能完全不同,这个时候共用一个实例就没办法支持了。所以为了封装可以更通用,更具灵活性,我会使用axios的create方法,使每次发请求都是新的axios实例。

// src/utils/http.js//...class NewAxios {  //...  request(options) {    // 每次请求都会创建新的axios实例。    const instance = axios.create();    const config = { // 将用户传过来的参数与公共配置合并。      ...options,      baseURL: this.baseURL,      timeout: this.timeout,      withCredentials: this.withCredentials,    };    // 配置拦截器,支持根据不同url配置不同的拦截器。    this.setInterceptors(instance, options.url);    return instance(config); // 返回axios实例的执行结果  }}

登录后复制

因为拦截器配置内容比较多,所以封装成一个内部函数了。

配置请求拦截器

在发送请求前对请求参数做的所有修改都在这里统一配置。比如统一添加token凭证、统一设置语言、统一设置内容类型、指定数据格式等等。做完后记得返回这个配置,否则整个请求不会进行。

我这里就配置一个token。

// src/utils/http.js//...class NewAxios {  //...  // 这里的url可供你针对需要特殊处理的接口路径设置不同拦截器。  setInterceptors = (instance, url) => {     instance.interceptors.request.use((config) => { // 请求拦截器      // 配置token      config.headers.AuthorizationToken = localStorage.getItem('AuthorizationToken') || '';      return config;    }, err => Promise.reject(err));  }  //...}

登录后复制配置响应拦截器

在请求的then或catch处理前对响应数据进行一轮预先处理。比如过滤响应数据,更多的,是在这里对各种响应错误码进行统一错误处理,还有断网处理等等。

我这里就判断一下403和断网。

// src/utils/http.js//...class NewAxios {  //...  setInterceptors = (instance, url) => {    //...    instance.interceptors.response.use((response) => { // 响应拦截器      // todo: 想根据业务需要,对响应结果预先处理的,都放在这里      console.log();      return response;    }, (err) => {      if (err.response) { // 响应错误码处理        switch (err.response.status) {          case '403':            // todo: handler server forbidden error            break;            // todo: handler other status code          default:            break;        }        return Promise.reject(err.response);      }      if (!window.navigator.online) { // 断网处理        // todo: jump to offline page        return -1;      }      return Promise.reject(err);    });  }  //...}

登录后复制

另外,在拦截器里,还适合放置loading等缓冲效果:在请求拦截器里显示loading,在响应拦截器里移除loading。这样所有请求就都有了一个统一的loading效果。

默认导出新的实例

  // src/utils/http.js    //...  export default new NewAxios();

登录后复制

最后完整的代码如下:

// src/utils/http.jsimport axios from 'axios';const getBaseUrl = (env) => {  let base = {    production: '/',    development: 'http://localhost:3000',    test: 'http://localhost:3001',  }[env];  if (!base) {    base = '/';  }  return base;};class NewAxios {  constructor() {    this.baseURL = getBaseUrl(process.env.NODE_ENV);    this.timeout = 10000;    this.withCredentials = true;  }  // 这里的url可供你针对需要特殊处理的接口路径设置不同拦截器。  setInterceptors = (instance, url) => {    instance.interceptors.request.use((config) => {      // 在这里添加loading      // 配置token      config.headers.AuthorizationToken = localStorage.getItem('AuthorizationToken') || '';      return config;    }, err => Promise.reject(err));    instance.interceptors.response.use((response) => {      // 在这里移除loading      // todo: 想根据业务需要,对响应结果预先处理的,都放在这里      return response;    }, (err) => {      if (err.response) { // 响应错误码处理        switch (err.response.status) {          case '403':            // todo: handler server forbidden error            break;            // todo: handler other status code          default:            break;        }        return Promise.reject(err.response);      }      if (!window.navigator.online) { // 断网处理        // todo: jump to offline page        return -1;      }      return Promise.reject(err);    });  }  request(options) {    // 每次请求都会创建新的axios实例。    const instance = axios.create();    const config = { // 将用户传过来的参数与公共配置合并。      ...options,      baseURL: this.baseURL,      timeout: this.timeout,      withCredentials: this.withCredentials,    };    // 配置拦截器,支持根据不同url配置不同的拦截器。    this.setInterceptors(instance, options.url);    return instance(config); // 返回axios实例的执行结果  }}export default new NewAxios();

登录后复制

现在 axios 封装算是完成了80%。我们还需要再进一步把axios和接口结合再封装一层,才能达到我在一开始定的封装目标。

3. 使用新的 axios 封装API

在 src 目录下新建 api 文件夹。把所有涉及HTTP请求的接口统一集中到这个目录来管理。新建 home.js。我们需要把接口根据一定规则分好类,一类接口对应一个js文件。这个分类可以是按页面来划分,或者按模块等等。为了演示更直观,我这里就按页面来划分了。实际根据自己的需求来定。使用新的 axios 封装API(固定url的值,合并用户传过来的参数),然后命名导出这些函数。

// src/api/home.js import axios from '@/utils/http';export const fetchData = options => axios.request({  ...options,  url: '/data',});export default {};

登录后复制

在 api 目录下新建 index.js,把其他文件的接口都在这个文件里汇总导出。

 // src/api/index.js    export * from './home';

登录后复制

这层封装将我们的新的axios封装到了更简洁更语义化的接口方法中。

现在我们的目录结构长这样:

|–public/
|–mock/
|   |–db.json  # 接口模拟数据
|–src/
|   |–api/     # 所有的接口都集中在这个目录下
|       |–home.js  # Home页面里涉及到的接口封装在这里
|       |–index.js # 项目中所有接口调用的入口
|   |–assets/
|   |–components/
|   |–router/
|   |–store/
|   |–utils/
|       |–http.js  # axios封装在这里
|   |–views/
|       |–Home.Vue
|   |–App.vue
|   |–main.js
|   |–theme.styl
|–package.json
|…

4.使用封装后的axios

现在我们要发HTTP请求时,只需引入 api 下的 index.js 文件就可以调用任何接口了,并且用的是封装后的 axios。

// src/views/Home.vue  
    

This is home page

  
// @ is an alias to /srcimport { fetchData } from '@/api/index';export default { name: 'home', mounted() { fetchData() // axios请求在这里 .then((data) => { console.log(data); }) .catch((err) => { console.log(err); }); },};

登录后复制

axios请求被封装在fetchData函数里,页面请求压根不需要出现任何axios API,悄无声息地发起请求获取响应,就像在调用一个简单的 Promise 函数一样轻松。并且在页面中只需专注处理业务功能,不用被其他事物干扰。

以上就是解析vue中axios的封装请求(附步骤代码)的详细内容,更多请关注【创想鸟】其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。

发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/3231719.html

(0)
上一篇 2025年4月1日 17:00:19
下一篇 2025年2月26日 22:12:15

AD推荐 黄金广告位招租... 更多推荐

相关推荐

  • VUE组件的创建、渲染、及注册(总结分享)

    本篇文章给大家带来了关于vue的相关知识,其中主要介绍了关于组件的创建、渲染以及注册的相关问题,创建的组件不要写el因为最终所有的组件都要被vm管理,由vm决定服务的对象,下面一起来看一下,希望对大家有帮助。 【相关推荐:vue、vue】 …

    2025年4月1日
    100
  • 简单分析vue组件scoped的作用

    本篇文章给大家带来了关于vue的相关知识,其中主要介绍了关于scoped属性的相关问题,在style上加入scoped属性, 就会在此组件的标签上加上一个随机生成的data-v开头的属性,下面一起来看一下,希望对大家有帮助。 【相关推荐:v…

    2025年4月1日 编程技术
    100
  • 详解v-bind怎么动态绑定style属性

    v-bind怎么动态绑定style属性?本篇文章带大家详细了解一下v-bind指令动态绑定style属性的多种语法,希望对大家有所帮助! v-bind可以动态设置style属性,用以绑定内联样式。写法: 登录后复制 一、v-bind动态绑定…

    2025年4月1日 编程技术
    100
  • 实例解决vue中使用lang=“scss“出现的报错

    本篇文章给大家带来了关于vue的相关知识,其中主要介绍了关于使用 lang=“scss“ 报错的相关问题,这是因为当前sass-loader的版本太高,webpack编译时出现了错误,下面一起来看一下,希望对大家有帮助。 【相关推荐:vue…

    2025年4月1日
    100
  • 详解v-bind怎么动态绑定class属性

    v-bind怎么动态绑定class属性?本篇文章带大家详细了解一下v-bind指令动态绑定class属性的多种语法,希望对大家有所帮助! v-bind可以动态设置class属性,用以实现动态样式。写法: 登录后复制 一、v-bind动态绑定…

    2025年4月1日 编程技术
    100
  • Vue中父组件向子组件传递数据的方法

    本篇文章给大家带来了关于vue的相关知识,其中主要总结了几种vue中父子组件传递数据的方法,包括了props & event、ref属性、provide & inject等等内容,具有一定的参考价值,下面一起来看一下,希望对…

    2025年4月1日
    100
  • 通俗易懂!详解VUEX状态仓库管理

    vuex 是一个专为 vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。简单来说就是:应用遇到多个组件共享状态时,使用vuex。 VueX 是一个专门为 V…

    2025年4月1日
    100
  • 实例介绍Vue通过$emit方法实现子父组件通信

    本篇文章给大家带来了关于vue的相关知识,其中主要介绍了关于$emit的相关问题,在子组件中通过$emit来调用父组件中的方法实现,下面一起来看一下,希望对大家有帮助。 【相关推荐:vue、vue】 Vue可以通过props属性,将参数从父…

    2025年4月1日
    100
  • 深入了解Vue计算属性computed的使用

    计算属性是 vue 组件的一个重要内容,下面本篇文章就来带大家了解一下vue computed属性,聊聊计算属性computed的使用方法,希望对大家有所帮助! Vue中的computed属性称为计算属性。在这一节中,我们学习Vue中的计算…

    2025年4月1日
    100
  • Vue详解之增加组件扩展性的slot

    本篇文章给大家带来了关于vue的相关知识,其中主要介绍了增加组件扩展性的slot的相关问题,组件的插槽也是为了让我们封装的组件更加具有扩展性,让使用者可以决定组件内部的一些内容到底展示什么,下面一起来看一下,希望对大家有帮助。 【相关推荐:…

    2025年4月1日
    100

发表回复

登录后才能评论