【Axios学习 二】一文通透Axios跨域和封装

目录

一、跨域

1.1 ProxyTable

1. 找到 config/index.js 文件中的 proxyTable:{} 将其修改

2. 找到 config/dev.env.js 文件,配置BASE_URL

3. 找到 config/prod.env.js 文件,配置BASE_URL

4. 配置 axios 的基础域名

二、封装

1.1 条件准备

2.2 axios封装(单域名)


一、跨域

因为在Vue的开发阶段,基本都是用webpack打包编译,需要node环境本地运行,因而运行的域名为本地的localhost,这个时候调用后端接口就涉及到跨域的问题了。

1.1 ProxyTable

vue 的 proxyTable 是用于开发阶段配置跨域的工具,可以同时配置多个后台服务器跨越请求接口,其真正依赖的npm包是 http-proxy-middleware, 在GitHub上拥有更丰富的配置,可以按需配置

在不考虑后端CROS跨域方案的情况下,前端配置ProxyTable实现跨域请求的用法如下:

1. 找到 config/index.js 文件中的 proxyTable:{} 将其修改

 proxyTable: {
  '/api': {
    target: 'https://tasst.sinoxk.cn', // 这个是你要代理的地址(开发阶段接口地址)
    changeOrigin: true, //跨域需要加上这个
    pathRewrite: {
      '^/api': '' //可以理解为用 / api代表target里的地址
    }
  }
} 

proxyTable支持配置多个接口:

  proxyTable: {
  '/api': {
    target: 'https://tasst.sinoxk.cn', // 这个是你要代理的地址(开发阶段接口地址)
    changeOrigin: true, //跨域需要加上这个
    pathRewrite: {
      '^/api': '' //可以理解为用 / api代表target里的地址
    }
  },
   '/service': {
    target: 'https://tasst.sinoxk.cn', // 这个是你要代理的地址(开发阶段接口地址)
    changeOrigin: true, //跨域需要加上这个
    pathRewrite: {
      '^/service': '' //可以理解为用 / api代表target里的地址
    }
  }
} 

2. 找到 config/dev.env.js 文件,配置BASE_URL

module.exports = merge(prodEnv, {
  NODE_ENV: '"development"',
  BASE_URL:'"/api"'  //开发环境域名
})

3. 找到 config/prod.env.js 文件,配置BASE_URL

module.exports = {
  NODE_ENV: '"production"',
  BASE_URL:'"https://asst.sinoxk.com"' //生产环境保持正式域名
}

4. 配置 axios 的基础域名

axios.defaults.baseURL = process.env.BASE_URL

修改完所有的配置文件后,要注意,需要重启下环境

npm run dev / npm run start 

二、封装

在日常项目开发过程中,在和后台交互获取数据的时候,我们都需要使用到网络库,通常在vue的项目中 ,使用的是 axios 库 ,在此基于自身项目业务,做一个二次封装。

1.1 条件准备

在UI轻提示组件上,选定的是 vant 库中的 Toast 组件(Vant文档),可按实际需要选定具体要使用的UI框架

安装:

npm install vant --save

数据序列化,如果有实际需要的项目,可以使用qs,在这里做一个简单的介绍

安装:

npm install qs --save

qs.stringify和JSON.stringify的使用和区别:

qs.stringify()将对象 序列化成URL的形式,以&进行拼接

JSON.stringify 是将对象转化成一个json字符串的形式

用法:

 var a = {name:'xiaoming',age:10}
  
  qs.stringify(a); //log: 'name=xiaoming&age=10'

  JSON.stringify(a) //log: '{"name":"hehe","age":10}'

基于底层配置和业务接口分离,在src目录中会新建文件夹 httpServer,同时新建立 ajax.js 和 api.js 文件

ajax.js: axios的二次封装,作为基础网络库,添加基础的配置
api.js: 管理项目实际业务基础接口的输出,以及返回响应数据的处理

在日常项目模块中,基于多人开发,当然可以在api.js的基础上,可以根据功能模块实现业务拓展延伸,比如

小明负责list模块业务

新建api-list.js,并导入api.js .... 

//api-list.js文件中:
import api from './api'

export default {
    getList(url,params){
        api.get(url,params)
    }
}

对于个别项目,可能存在多个域名配置的情况下, 可以重新建立 base.js , 来管理多个接口域名

base.js:

/**
 * 接口域名的管理
 */
const base = {
  sq: 'https://xxxx111111.com/api/v1',
  bd: 'http://xxxxx22222.com/api'
}

export default base;

2.2 axios封装(单域名)

src/main.js文件:

import Vue from 'vue'
import App from './App'
import router from './router'
import Api from './httpServer/api'

//挂载到vue的全局属性上
Vue.prototype.$https = Api

Vue.config.productionTip = false

new Vue({
  el: '#app',
  router,
  components: { App },
  template: '<App/>'
})

src/httpServer/ajax.js文件:

import axios from 'axios'
import {Toast} from 'vant'


const ajax = axios.create({
     timeout:60000,
     baseURL:process.env.BASE_URL   //基础域名
})


/**
 * 请求拦截器
 * 每次请求前,如果存在token则在请求头中携带token
 */
ajax.interceptors.request.use(
  config => {
    //判断token(根据实际情况拦截)
   
    return config;
  },
  error => Promise.error(error)
)

/**
 * 响应拦截器
 */
ajax.interceptors.response.use(
  // 请求成功
  res => res.status === 200 ? Promise.resolve(res) : Promise.reject(res),
  error => {
    const {response} = error;
    if (response) { // 请求已发出,但是不在2xx的范围
      Toast({message: response.message});
      return Promise.reject(response);
    } else {
      // 处理断网的情况
      // eg:请求超时或断网时,更新state的network状态
      // network状态在app.vue中控制着一个全局的断网提示组件的显示隐藏
      // 关于断网组件中的刷新重新获取数据,会在断网组件中说明
      Toast({message: '网络开小差,请稍后重试'});
    }
  }
)

export default ajax;

对于process.env.BASE_URL的配置,在开发环境中,需要以代理的方式进行访问:

//config/dev.env.js

'use strict'
const merge = require('webpack-merge')
const prodEnv = require('./prod.env')

module.exports = merge(prodEnv, {
  NODE_ENV: '"development"',
  BASE_URL:'"/api"'  //对api进行处理
})
//config/prod.env.js

'use strict'
module.exports = {
  NODE_ENV: '"production"',
  BASE_URL:'"https://www.xxx.com"' //生产环境不需要处理
}
//config/index.js
...

   proxyTable: {
       '/api': {
        target: 'https://tasst.sinoxk.cn',//后端接口地址
        changeOrigin: true,//是否允许跨越
        pathRewrite: {
          '^/api': '',//重写(接口地址带api会被替换)
        },
      }
    },
...

src/httpServer/api.js文件:

import ajax from './ajax'
import {Toast} from 'vant'

/**
 *  业务接口成功或者失败的情况处理
 *
 */
const handleResponse = (res, success, failure) => {
  switch (res.code) {
    case 200:   //成功
      success && success(res.data);
      break;
    case 401:   //登录token失效

      break;
    default:
      if (failure) {
        failure(res);
      } else {
        Toast({message:res.msg || '请求失败,请稍后重试!'});
      }
      break;
  }
}

export default {
  get: function (url, params, success, failure) {
    ajax.get(url, {
      params: params
    }).then(res => {
      if (res.status == 200) {
        handleResponse(res.data.data, success, failure);
      }
    });
  },

  post: function (url, params, success, failure) {
    ajax.post(url, params).then(res => {
      if (res.status == 200) {
        handleResponse(res.data.data, success, failure);
      }
    })
  }
}

src/components/HelloWorld.vue文件中使用:

<script>
  export default {
    name: 'HelloWorld',
    data() {
      return {
        msg: 'Welcome to Your Vue.js App'
      }
    },
    created() {
     //请求接口数据
      this.$https.get('/xkzx/member/service', {
        pageNum: 1,
        pageSize: 10
      }, function (data) { //成功
         console.log(data);

      }, function (res) {  //失败

      })

    }
  }
</script>

猜你喜欢

转载自blog.csdn.net/yzq0820/article/details/127564641
今日推荐