vue-axios的总结及项目中的常见封装方法。

前言

  我们知道 vue 2.0版本开始推荐使用 axios 来完成前端 ajax 请求,axios 是一个基于Promise 的 http 库,可以用在浏览器和 node.js 中,axios 成为vue全家桶的一个重要部分,对前后端接口请求起着必不可少的作用,本文主要总结一下 axios 的一些小知识点和项目中常见的需要封装的方法。

正文

  1.axios 是什么?

  axios 是一个基于 Promise 的 http 库,可以用于浏览器和 node.js 中,在浏览器中创建 XMLHttpRequest 对象(基于ajax的一种封装),然后调用该对象的一些方法实现对后端数据接口的请求,在 node.js 中用于创建 http 请求,支持 Promise Api,可以使用 async/await 语法糖书写,便于拦截请求和响应,并对请求和响应的数据进行处理,自动转换 JSON 数据格式,同事用于客户端支持防御 XSRF。且目前主流浏览器都支持该库。

  常见的安装方式有以下两种:

  (1)使用 cdn 方式,代码中直接引入下面脚本即可,这种方式适用于小型项目,比如学习的小 demo 等。

    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>

 

  (2)使用 npm 方式,直接在命令行中添加即可。

    npm install axios

 

  2.axios 常见用法?

  axios中常用的请求配置如下,只有指定的url是必须项,其他存在默认配置项,method不特殊指定,默认方法为 get 。

  {
    url: '/user',
  // `url` 是用于请求的服务器 URL    method: 'get',
  // default `method` 是创建请求时使用的方法    baseURL: 'https://some-domain.com/api/',
  // `baseURL` 将自动加在 `url` 前面,除非 `url` 是一个绝对 URL。它可以通过设置一个 `baseURL` 便于为 axios 实例的方法传递相对 URL   headers: {'X-Requested-With': 'XMLHttpRequest'},
  // `headers` 是即将被发送的自定义请求头   params: {   ID: 12345   },
  // 必须是一个无格式对象(plain object)或 URLSearchParams 对象,`params` 是即将与请求一起发送的 URL 参数   timeout: 1000,
  // 如果请求话费了超过 `timeout` 的时间,请求将被中断,`timeout` 指定请求超时的毫秒数(0 表示无超时时间)   withCredentials: false,
  // default `withCredentials` 表示跨域请求时是否需要使用凭证    responseType: 'json',
  // default `responseType` 表示服务器响应的数据类型,可以是 'arraybuffer', 'blob', 'document', 'json', 'text', 'stream'    responseEncoding: 'utf8', // default   onUploadProgress: function (progressEvent) {
  // `onUploadProgress` 允许为上传处理进度事件   // Do whatever you want with the native progress event    },    onDownloadProgress: function (progressEvent) {
  // `onDownloadProgress` 允许为下载处理进度事件   // 对原生进度事件的处理    },   }

  (1)get 请求

 

    axios.get('url',{params:{
        //这里是请求参数
    }})
    .then(res=>{
    //这里是响应后操作 }) .
catch(err=>{
    //异常捕获 })

 

  (2)post 请求

    axios.post('url',{  
        name:xxx//参数  
    },{  
        headers:xxxx,//请求头信息
    })
    .then(function(res){  
        //处理成功的函数 相当于success
    })
    .catch(function(error){  
        //错误处理 相当于error
    })

  (3)all、spread 并发请求

    axios.all([
    axios.get('url'),
    axios.get('url',{params:{type:'sell',page:1}})
    ])
    .then(axios.spread((res1,res2)=>{
        //返回结果为一个数组
    }))

  all()方法入参为一个数组,数组元素是每一项请求,回调函数 .then() 的参数也是一个数组,里面的每一项元素表示前面请求的返回结果,使用了 axios.spread作为该回调函数的参数时,其res1,res2分别代表前面每一项请求的返回结果。

  综上这些方法都只使用于小型项目中,或者学习小 demo 中,在工作开发中遇到处理的请求接口较多,

 

  3.axios 在项目中的常见用法?

  (1)小型项目中常见封装方法,灵活性较高。

  首先创建 axios.js 文件

     import originAxios from 'axios'
    export default  function axios(option){
        return new Promise((resolve,reject)=>{
            //创建axios实例
            const instance=originAxios.create({
                baseURL:'/api',
                timeout:5000,
                headers:''
            });
            //传入对象进行网络请求
            instance(option)
            .then(res=>{
                resolve(res)
            })
            .catch(err=>{
                reject(err)
            })
        })
    }

  然后在需要发送请求接口的地方引入

    import {axios} from './axios.js'

    axios({method:"get",url:"url",params:{...}})
    .then(res=>{
        //请求数据后操作
    })
    .catch(err=.{
        //错误处理
    })    

 

  (2)针对不同请求类型进行二次封装。

    /* *url:请求的url
       *params:请求的参数
       *config:请求时的header信息
       *method:请求方法 */
      const request = function ({ url, params, config, method }) {
        // 如果是get请求 需要拼接参数
        let str = "";
        if (method === "get" && params) {
          Object.keys(params).forEach((item) => {
            str += `${item}=${params[item]}&`;
          });
        }
        return new Promise((resolve, reject) => {
          axios[method](
            str ? url + "?" + str.substring(0, str.length - 1) : url,
            params,
            Object.assign({}, config)
          )
            .then(
              (response) => {
                resolve(response.data);
              },
              (err) => {
                if (err.Cancel) {
                } else {
                  reject(err);
                }
              }
            )
            .catch((err) => {
              reject(err);
            });
        });
      };

  具体使用同上。

  (3)基于请求响应拦截进行封装,实际项目开发中常用。

  axios 提供的拦截器,用于每次发送请求和得到响应后进行响应的处理。比如在请求拦截中可以在页面中添加 loading 动画,某些请求要求用户必须登录,判断用户是否有token,如果没有就跳转到登录页面等,也可以对请求参数进行序列化操作等 config.data = qs.stringfy(config.params) 等。同样,响应拦截也可以对响应的数据进行过滤,包括响应失败的拦截,可以根据响应状态码进行不同的操作等。具体方法如下:

  首先在工具方法文件夹中创建 request.js 文件。这里搭配了token用于判断用户状态,element-ui 组件处理一些错误报错提示。该文件封装暴露了get、post、文件上传方法。

      import axios from "axios";
      import store from "../store";
      import { Message, MessageBox } from "element-ui";

      let baseURL = "http://127.0.0.1:3000/";
      // 创建axios实例
      const service = axios.create({
        baseURL: baseURL,
        timeout: 5000, // 请求超时时间
        headers: { "Content-Type": "application/json;charset=UTF-8" },
      });
      // axios.defaults.withCredentials = true; // 若跨域请求需要带 cookie 身份识别
      axios.defaults.headers.post["Access-Control-Allow-Origin-Type"] = "*"; // 允许跨域
      const err = (error) => {
        if (error.response) {
          let data = error.response.data;
          const token = store.getters.token;
          switch (error.response.status) {
            case 403:
              Message({
                message: data.message,
                type: "error",
                duration: 5 * 1000,
              });
              break;
            case 500:
              if (token && data.message == "Token失效,请重新登录") {
                MessageBox.confirm(
                  "很抱歉,登录已过期,请重新登录",
                  "确定登出",
                  {
                    confirmButtonText: "重新登录",
                    cancelButtonText: "取消",
                    type: "warning",
                  }
                ).then(() => {
                  store.dispatch("Logout").then(() => {
                    window.location.reload(); // 为了重新实例化vue-router对象 避免bug
                  });
                });
              }
              break;
            case 404:
              Message({
                message: data.message,
                type: "error",
                duration: 5 * 1000,
              });

              break;
            case 504:
              Message({
                message: data.message,
                type: "error",
                duration: 5 * 1000,
              });
              break;
            case 401:
              Message({
                message: data.message,
                type: "error",
                duration: 5 * 1000,
              });
              if (token) {
                store.dispatch("Logout").then(() => {
                  setTimeout(() => {
                    window.location.reload();
                  }, 1500);
                });
              }
              break;
            default:
              Message({
                message: data.message,
                type: "error",
                duration: 5 * 1000,
              });
              break;
          }
        }
        return Promise.reject(error);
      };
      // request拦截器
      service.interceptors.request.use(
        (config) => {
          const token = store.getters.token;
          if (store.getters.token) {
            config.headers["X-Token"] = token;//这里要注意在判断用户状态时候,请求头添加x-token格式问题,大写分开。
          }
          return config;
        },
        (error) => {
          // Do something with request error
          console.log(error); // for debug
          Promise.reject(error);
        }
      );
      // respone拦截器
      service.interceptors.response.use((response) => {
        console.log("response.data", response.data);
        return response.data;
      }, err);

      /*
       *  get请求
       *  url:请求地址
       *  params:参数
       * */
      export function get(url, params = {}) {
        return new Promise((resolve, reject) => {
          console.log("process.env.BASE_API", process.env.BASE_API);
          service({
            url: url,
            method: "get",
            params: params,
          })
            .then((response) => {
              resolve(response);
            })
            .catch((error) => {
              reject(error);
            });
        });
      }

      /*
       *  post请求
       *  url:请求地址
       *  params:参数
       * */
      export function post(url, params = {}) {
        return new Promise((resolve, reject) => {
          service({
            url: url,
            method: "post",
            data: params,  //这里注意下请求数据放在query params还是body中。
          })
            .then((response) => {
              resolve(response);
            })
            .catch((error) => {
              reject(error);
            });
        });
      }

      /*
       *  文件上传
       *  url:请求地址
       *  params:参数
       * */
      export function fileUpload(url, params = {}) {
        return new Promise((resolve, reject) => {
          console.log("@@@@@@@@@@@params", params);
          service({
            url: url,
            method: "post",
            data: params,
            headers: { "Content-Type": "multipart/form-data" },
          })
            .then((response) => {
              resolve(response);
            })
            .catch((error) => {
              reject(error);
            });
        });
      }

      export default {
        get,
        post,
        fileUpload,
      };

 

  然后创建api文件夹,如果接口过多可以对接口进行模块化管理,比如我这 api 下面创建 login.js 文件。

import { get, post,fileUpload } from "../utils/request";

// 登录
export const login = (params) => {
  return get("/user/login", { ...params });
};
// 查询用户信息
export const getUserInfo = (params) => {
  return get("/user/userInfo", { ...params });
};
// 上传音频文件
export const addRadioApi = (params, file) => {
  return fileUpload("/radio/addRadio", { params, file });
};

  最后在你的vue文件中就可以使用了,login.vue中使用如下:

      import { login } from "../../api/login";
      login({ name: "123", password: "123456" })
        .then((res) => {
          //登录请求后操作
        })
        .catch((error) => {
          //异常处理
        });

总结

  以上就是本文的全部内容,希望给读者带来些许的帮助和进步,方便的话点个关注,小白的成长踩坑之路会持续更新一些工作中常见的问题和技术点。

 

posted @ 2021-05-09 16:05  丶Serendipity丶  阅读(268)  评论(0编辑  收藏  举报