最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 在vue中封装axios并实现api接口的统一管理

    正文概述 掘金(FTD止水)   2020-12-25   913

    在vue项目中,我们通常都是使用axios与后台进行数据交互,axios有很多好用的特性,这里不多做介绍,相关细节可以查阅axios中文网。在对axios进行封装之前,我们要使用vue脚手架工具创建一个vue项目(这里我用的是cli4)。

    安装

    cnpm install axios --save-dev; // 安装axios
    cnpm install qs --save-dev; // 安装qs模块,用来序列化post类型的数据,否则后端无法接收到数据
    

    模块引入

    src目录下创建一个service目录,用于存放接口封装的相关文件。然后在service目录中创建service.js,用于axios、qs模块的引入,并在此文件中对axios进行封装。代码如下(接口域名只有一个的情况):

    import axios from 'axios'    //引入axios
    import qs from 'qs'    //引入qs,用来序列化post类型的数据,否则后端无法接收到数据
    // 设置post请求头
    axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8';
    axios.defaults.withCredentials = false;//在跨域请求时,不会携带用户凭证;返回的 response 里也会忽略 cookie
    
    //创建axios实例,请求超时时间为300秒
    const instance = axios.create({
      timeout: 300000,
    });
    
    //请求和响应拦截可以根据实际项目需求进行编写
    // 请求发起前拦截
    instance.interceptors.request.use((config) => {
    //这里可以对接口请求头进行操作 如:config.headers['X-Token'] = token
      console.log("请求拦截",config);
      return config;
    }, (error) => {
      // Do something with request error
      return Promise.reject(error)
    })
    
    // 响应拦截(请求返回后拦截)
    instance.interceptors.response.use(response => {
      console.log("响应拦截",response);
      return response;
    }, error => {
      console.log('catch', error)
      return Promise.reject(error)
    })
    
    //按照请求类型对axios进行封装
    const api={
        get(url,data){
    	return instance.get(url,{params:data})
        },
        post(url,data){
    	return instance.post(url,qs.stringify(data))	
        }, 
    }
    export {api}
    

    上述代码是接口域名只有一个的情况(多数情况),当接口域名有多个的时候(少数情况),我们需要对之前的封装进行改造,代码如下:

    import axios from 'axios'    //引入axios
    import qs from 'qs'    //引入qs,用来序列化post类型的数据,否则后端无法接收到数据
    // 设置post请求头
    axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8';
    axios.defaults.withCredentials = false;//在跨域请求时,不会携带用户凭证;返回的 response 里也会忽略 cookie
    
    //创建axios实例,请求超时时间为300秒,因为项目中有多个域名,所以对应的也要创建多个axios实例
    const instanceA = axios.create({
      timeout: 300000,
    });
    const instanceB = axios.create({
      timeout: 300000,
    });
    
    //如果项目为单一域名,这里可以不用进行配置,当项目接口有多个域名时,要对axios实例基础路径进行配置,否则在项目生产环境中无法进行区别调用
    if (process.env.NODE_ENV == 'production') {
        instanceA.defaults.baseURL = 'https://www.production_a.com';
        instanceB.defaults.baseURL = 'https://www.production_b.com';
    }
    
    //请求和响应拦截可以根据实际项目需求进行编写
    // 请求发起前拦截
    instanceA.interceptors.request.use((config) => {
    //这里可以对接口请求头进行操作 如:config.headers['X-Token'] = token
      console.log("请求拦截",config);
      return config;
    }, (error) => {
      // Do something with request error
      return Promise.reject(error)
    })
    instanceB.interceptors.request.use((config) => {
      console.log("请求拦截",config);
      return config;
    }, (error) => {
      // Do something with request error
      return Promise.reject(error)
    })
    
    // 响应拦截(请求返回后拦截)
    instanceA.interceptors.response.use(response => {
      console.log("响应拦截",response);
      return response;
    }, error => {
      console.log('catch', error)
      return Promise.reject(error)
    })
    instanceB.interceptors.response.use(response => {
      console.log("响应拦截",response);
      return response;
    }, error => {
      console.log('catch', error)
      return Promise.reject(error)
    })
    
    //按照请求类型对axios进行封装
    const api={
        get(url,data){
    	return instanceA.get(url,{params:data})
        },
        post(url,data){
    	return instanceA.post(url,qs.stringify(data))	
        },
        doGet(url,data){
    	return instanceB.get(url,{params:data})
        },
        doPost(url,data){
    	return instanceB.post(url,qs.stringify(data))	
        }    
    }
    export {api}
    

    上述代码中有根据生产环境对axios实例的基础路径进行配置,如果项目中有多个环境(如:测试环境等),则需要对CLI4脚手架环境变量进行配置,配置方法可以参见我在简书上写的一篇文章Vue CLI4环境变量的配置。

    api接口统一管理

    将api接口按照功能模块进行拆分,把同一模块下的接口写在同一个文件中进行统一管理,这样代码会更容易维护。比如我们的项目中有新闻模块,音乐模块等。我们就在serviec目录中创建news.jsmusic.js文件,用于管理各自模块的所有api接口,这里我只拿news.js文件为例,代码如下:

    import {api} from "./service.js";	
    const news={
    	getNewsList(){//获取新闻列表
    		return api.get("api/news/getNewsList")
    	},
    	editNewsDetail(data){//修改新闻详情
    		return api.post("api/news/editNewsDetail",data);
    	}
    }
    export default news;
    

    为了更方便在项目中调用这些封装好的接口,我们需要将这些接口挂载到vue的原型上,首先我们要在service目录中创建api.js文件,将所有模块的api管理文件引入进来,然后进行统一导出,代码如下:

    //引入相关api管理模块
    import news from "./news.js";
    //进行统一导出
    export default {
    	news
    }
    

    找到项目中的main.js文件,将接口挂载到vue的原型上,代码如下:

    import Vue from 'vue'
    import App from './App.vue'
    import router from './router'
    import store from './store'
    import axios from 'axios'
    Vue.prototype.axios=axios
    Vue.config.productionTip = false
    import api from "./service/api.js";
    //将封装的接口挂载到vue原型上
    Vue.prototype.$api = api;
    new Vue({
      router,
      store,
      render: h => h(App)
    }).$mount('#app')
    

    然后我们在项目创建完成时自动生成的模板文件App.vue调用封装好的接口,代码如下:

    <template>
      <div id="app">
        <div id="nav">
    	<router-link to="/">Home</router-link> |
    	<router-link to="/about">About</router-link>
    	<button @click="getN">接口封装getN</button>
    	<button @click="postN">接口封装postN</button>
        </div>
        <router-view/>
      </div>
    </template>
    <script>
    
    export default {
    	methods:{
    		getN(){
    			this.$api.news.getNewsList().then((res)=>{
    				console.log(res);
    			})
    		},
    		postN(){
    			let openid="oO5tQ5VMPpuzLqwfXhpmwjqwSANM";
    			let productCodes="pro-1337270496655446016";			
    			this.$api.news.editNewsDetail({openid,productCodes}).then((res)=>{
    				alert(res.data.msg);
    			})
    		}
    	}	
    }
    </script>
    <style lang="scss">
    #app {
      font-family: Avenir, Helvetica, Arial, sans-serif;
      -webkit-font-smoothing: antialiased;
      -moz-osx-font-smoothing: grayscale;
      text-align: center;
      color: #2c3e50;
    }
    
    #nav {
      padding: 30px;
    
      a {
        font-weight: bold;
        color: #2c3e50;
    
        &.router-link-exact-active {
          color: #42b983;
        }
      }
    }
    </style>
    

    配置代理

    因为我们要在本地环境进行测试,这就涉及到了跨域问题,为了解决跨域问题,我们可以进行代理的配置,在项目根目录中创建vue.config.js文件,然后可以对项目进行各种配置,代理的配置方法如下:

    // vue.config.js
    module.exports = {
      // 输出文件目录
      outputDir: "dist",
      // eslint-loader 是否在保存的时候检查
      lintOnSave: false,
      // 基本路径
      publicPath: process.env.NODE_ENV === "production" ? "./" : "/",
      devServer: {
        host: "localhost",
        port: 8080,
        open: true,
        hotOnly: true, // 热更新
        // 设置代理
        proxy: {
          "/api": {
            // 本地mock服务器
            target: "https://www.xxxx.com/xxx/",
            changeOrigin: true,
            ws: false,				
          },
          //如果项目中存在多个域名接口,可依次进行配置
    	"/apib":{
    		target: "https://www.xxxx.com/xxx/",
    		changeOrigin: true,
    		ws: false,
    	},
        }, 
      },
    };
    

    代理配置好了之后,就可以运行项目了,命令行中输入npm run serve,项目启动好了之后,就可以进入页面点击按钮,测试之前做的封装是否好用。

    结语

    以上就是本人对vue中封装axios的一点心得,文章有错误或需要改进的地方还请与我联系,我将及时进行更正,感谢阅读。


    起源地下载网 » 在vue中封装axios并实现api接口的统一管理

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元