axios二次封装:防止重复请求,数据自动填充

381 阅读2分钟

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

axios二次封装是老生常谈的东西了。

读完文章你将知道:

  1. 如果避免一个接口多次请
  2. 可以免去在页面进行数据赋值
axios.get('xxx').then(res=>{
    this.tableList = res.data // 可以省略这些代码
})    

我们的目录结构是这样的

image.png

步骤一: 首先我们需要创建axios实例:
 // server.js
const server = axios.create({
    baseURL: 'xx',
    timeout: 5000
})
export default server
步骤二:其次将各模块的api文件维护起来

其中需要维护的属性包括请求路径和请求方式

// shop.js 以shop.js为例
export default {
    getShopList : {type:'get', url: '/shop/getShopList'}
}

// index.js api 入口文件
import shop from './shop.js'
import myserver from '../server/getrequest.js'

myserver.parseRoute('shop', shop)
myserver.parseRoute('xx', xx) //其他模块

export default myserver 
步骤三:然后就是请求部分的核心逻辑

这里就实现了防止重复请求和数据自动填充

  1. 首先创建一个myserver的类
  2. axios实例保存到类的server属性上
  3. v()方法是用来保存组件实例
  4. parseRoute()方法是给每个模块api属性绑定请求方法
  5. sendReq()对请求方法的封装(包括防止重复请求和数据自动填充)
// myserver.js
import server from './server.js'

function myserver (){
    this.server = server //保存一下axios 实例
    this.vueobj = null //vue实例
}

// 保存vue实例
myserver.prototype.v = function(vueobj){
    this.vueobj = vueobj
}

// 给各个模块的api的对象绑定请求方法
myserver.prototype.parseRoute = function(moduleName, apiObj){
    this[moduleName] = {}
    Object.keys(apiObj).forEach((apiName)=> {
        this[moduleName][apiName] = this.sendReq.bind(this, moduleName, apiName, apiObj[apiName])
        this[moduleName][apiName].state = 'ready' // 每个模块的每个api给个状态用来防止重复请求
    })
}
// 请求方法的封装
myserver.prototype.sendReq = function(moduleName, apiName, {type, url}, config){

    // 处理config  bindName就是通过api调用传入进来实现页面数据填充的变量名
    const {data, params, successCb, bindName } = config
    
    // 处理loading
    var before = function(res){
        this[moduleName][apiName].state = 'ready'
        return res
    }
    // 默认的成功回调
    var defaultFn = function(res){
        this.vueobj[bindName] = res.data
        return res
    }
    
    var success = successCb || defaultFn
    
    // 请求
    if(this[moduleName][apiName].state == 'ready'){
        this[moduleName][apiName].state == 'waiting'
        this.server[type](url, {data, params}).then(before).then(success)
    }
}

export default new myserver
最后一步:页面如何调用
<script>
import api from '@/api'
export default {
    mounted(){
        api.v(this)
    },
    data(){
        return {
            tableList: []
        }
    },
    methods:{
        getList(){
            // 这样传入bindName就实现了数据填充 
            api.shop.getShopList({data: {page: 1, limit: 10}}, {bindName: 'tableList'})
        }
    }
}
</script>

有疑问欢迎随时提问 !~