axios封装api

前言

本文涉及到axios,vuex,vuex/modules并且没有覆盖所有的项目情况,如果不符合你的技术栈,还请随便看看。

如果不愿意看作者扯淡,可以看github上的demo(typescript)

另外,这个demo是使用了vue-cli@3.0tsclass写的,如果不熟悉语法的,还请担待。本文章的语法会依然使用js。

不建议在vue中使用ts,目前还没有完全兼容,组件中使用vuex的action也会丢失类型监测等等,感觉ts的语法相比eslint的检测更适合团队。

欢迎来我的Vue技术群交流:887516034

Axios

首先先封装需要使用的请求api

//-- src/utils/api.js

import Axios from 'axios';
import qs from 'qs';
import store from '../store/'  //-- src/store/index.js
import Vue from 'vue'
import router from '../router/'
import myCookie from './cookie'    
//-- src/utils/cookie.js   这里使用的是mdn网站的cookie封装,附上链接
// https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie/Simple_document.cookie_framework

//create方法会创建一个新的axios实例,并继承axios几乎所有属性,配置和方法
//建议使用 create 方法封装 api ,不对 axios 本身做特殊配置
const api = Axios.create({
    //传参是一个对象,配置包含baseUrl,timeout等等,既可以在这里传进去,也可以在实例化后设置配置
    
    baseURL: process.env.NODE_ENV==="development"?'/api':'https://example.domain',
    // 设置通用url,使用请求的方法时,就可以省略这个url
    // 可以通过process.env.NODE_ENV判断是否开发环境,来决定是否使用代理url
    // 代理是用来解决跨域的。。
    
    headers: {
        //这个配置不用说了吧。默认携带请求头,
        //有的后台更喜欢让前端把session_id放在header里发送
    },
    
    transformRequest: [function (data, headers) {
        // 此处是格式化发请求时,需要发送的数据格式
        // 某些后台在处理数据时不识别默认的 payload
        // 此处用第三方模块qs 转换成 兼容较好的 form-data(x-www-form-urlencoded)
        return qs.stringify(data);
    }],
    
    timeout: 10000,//超时,超出这时间,就会Promise.reject(),单位ms
    
    withCredentials: true,
    // 允许浏览器端在发请求时,携带cookie一起发送,
    // 某些后台语言会把session_id放在cookie里返回给前端
    // 如果这时不允许发送cookie的话  那么后台会判断是另一个浏览器在登录操作。
    // 我都是在实例化后 配置这个属性 因为我偶尔出现在这里传参配置会无效。
    // 设置这个属性为true后 ,后台不可以把允许跨域设置为'*',必须指定ip或域名
    
    proxy:{}//axios的代理我没用过,不过看了下源码,也是开发环境才可以使用
});

//现在这里再给实例化后的api 配置拦截  不是axios本身
//添加请求拦截器
api.interceptors.request.use(config => {
  //在发送请求之前做某事,比如说 设置loading动画显示
  store.commit('loadingStart');
  //此处我是把全局loading动画的控制放在vuex的,所以引入了store
  return config
}, error => {
  //请求错误时做些事
  return Promise.reject(error)
});
//添加响应拦截器
api.interceptors.response.use(response => {
  //对响应数据做些事,比如说把loading动画关掉
  store.commit('loadingOver');
  return response.data
  //此处我直接返回res.data,方不方便你们应该有点b数的
}, error => {
  //请求错误时做些事
  // error.response.status是后台响应请求的状态码
  // 可以根据自己项目的需求  执行操作
  if (error.response.status===401){
  //这里引入vue是因为要使用挂载在vue原型上的element-ui的弹窗组件
  // 因为这时挂载vue原型上的方法,这个import的vue并没有实例化,无法省略prototype
    Vue.prototype.$alert(error.response.data.msg,{
      type:error.response.data.type,
      title:'Message',
    }).then(()=>{
      myCookie.removeItem('user');
      router.push({name:'SignIn'});//这里就是引入router的目的
      console.clear();
    })
  }
  store.commit('loadingOver');//关闭动画
  return Promise.reject(error)
});

api.defaults.withCredentials = true;
// 允许发送cookie,根据自己的项目需求是否需要开启
// axios的更多配置可以看官方的文档 github的 readme.md
// https://github.com/axios/axios   

export default api
复制代码

至此,一个简单常用的api的配置部分封装完成

这里提一下proxy的使用,好多人出过错。

// https://github.com/chimurai/http-proxy-middleware
'/api':{
    target:'http://example.domain',
    changeOrigin: true, //是否需要虚拟站点,我也不懂啥意思。。好像写不写差不多
    pathRewrite:{
        //这个属性,是看后台接口的请求url中是否有你配置的这个api
        //如果有的话你就不用写这个属性,
        //如果没有,你就需要写
        '^api':'',//把你本地请求的url中的api字段去掉
    }
}

//以上的配置效果是
//--  /api/xxx --->>>  http://example.domain/xxx
// 如果不写pathRewrite
//--  /api/xxx --->>>  http://example.domain/api/xxx
复制代码

当项目中需要多个url时,再建一个文件,再create一个实例就可以,使用哪个就引入哪个,分开维护,很方便。

Service

这里我们封装完api的url和请求配置部分,下面就要封装具体的请求。这里我定义为services

//-- src/services/user.js  这里可以把请求整理成模块,如果请求接口较多,后期维护方便

import api from '../utils/api'

// 参数是es6的解构,小白自己去看 阮老师 的 es6 
// USER_REGISTER声明为一个方法
export const USER_REGISTER = ({user,password,email,phone,code}) => {
  return api.post('/register',{//此处 post '/register' ===>>  baseURL+'/register'
    user,password,email,phone,code
    // es6 对象的键值对字符相同时的写法
  })
};//注册接口

export const USER_LOGIN = ({user,password}) => {
  return api.post('/signIn',{user,password});
};//登录接口

// 我这里导出的是多个方法名的集合,是一个对象,
// 可以通过 import { USER_LOGIN,USER_REGISTER } from '...' 使用
// 这里就举例 2个  不详细写了
复制代码

这里提一下,很多小伙伴对axios的使用文档不熟悉,在get和post时,经常出现2个方法的混肴,传参出错,建议对不熟悉语法的,不要使用‘省略式’的写法,下面可以看一下详细写法,可以减少出错率。(其实就是官方文档的。)

axios({
    url:'...',
    method:'...',
    headers:{},
    params:{},//这个是get携带请求参数用的,拼接在url的,直接写在url上也可以,
    data:{},// 这个是post put patch请求发送的数据
})
复制代码

Vuex

现在我们已经封装完成完整的api了,如果觉得没必要使用vuex,可以直接引入servicesuser.js直接使用了。

import { USER_LOGIN } from '@/services/user'

USER_LOGIN({user,password}).then().catch()
复制代码

为什么要用加入vuex,vuex的action是用来处理异步操作的,同时vuex的state是整个项目组件之间数据流动的重要环节,多数数据会在组件之间通用,将api请求放在action中可以更合理的读写state,不多说,上代码。

个人习惯,一用vuex就喜欢直接使用模块(namespaced),这里推荐vuex多使用模块,在团队开发中提供很大的便利,右转vuex官网

//-- src/store/modules/user/action.js
import { USER_INFO } from '@/services/user'

export default {
    async getInfo({ commit }){
        try{ //请求成功
            const data = await USER_INFO();
            commit('setUserInfo',data);
            //模块的action中使用commit,不需要使用namespace前缀
            return data
            // async函数的返回值,默认会以promise.resolve(data)的形式
        }catch(e){
        //请求失败或者代码块出错
            return e
        }
        
    }
}
//合理使用 async/await 可以让逻辑代码更清晰
复制代码
//--- src/store/modules/user/commit.js
export default {
    setUserInfo(state,data){
        state.info = data
    }
}
复制代码
<!-- 此处假设已经调用getInfo请求 -->
<template>
    <div>
        <p>{{info.name}}</p>
        <p>{{info.age}}</p>
        <img :src="info.photo" />
    </div>
</template>
<script>
import { mapState } from 'vuex'
export default{
    //...
    computed:{
        //需要使用模块中数据时,第一个参数为模块名
        ...mapState('user',{
            info:'info'
        })
    }
}
</script>
复制代码

tips:懂得分享才能走的更远。

欢迎来我的Vue技术群交流:887516034

如果觉得对你有用,就打赏一下吧。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值