vue配置axios与服务端交互的过程(包含跨域)

730 阅读3分钟

1.axios的配置与使用

a.在src中新建apiconfig/index.js文件,引入axios并进行请求响应的封装(以登陆接口为例)

// 配置axios拦截等
import axios from 'axios'
import store from '../store/index'
// import _ from 'lodash'    javascript库
import { Message, Loading } from 'element-ui'
// 初始化axios     创建axios实例
const service = axios.create({
  // baseURL: 判断是开发/生产环境
  baseURL: process.env.NODE_ENV === 'production' ? 'http://abc.com:8888/' : '/apis',
  timeout: 5000
})
// loading
let loading = null
let requestAll = 0 // 当有多个请求时
const showLoading = function (target) {
  if (!loading && requestAll === 0) {
    loading = Loading.service({
      target: target || 'body', // 显示的节点DOM
      lock: true,
      text: '加载中⭐⭐',
      background: 'rgba(255, 255, 255, 0.5)'
    })
  }
  requestAll++
}
// 关闭loading
const closeLoading = function () {
  requestAll--
  if (requestAll === 0) {
    loading ? loading.close() : (loading = null)
  }
}

// 请求拦截 用于封装请求headers等
service.interceptors.request.use(
  config => {
    // 拦截下来封装请求头
    showLoading()
    config.headers['Content-Type'] = 'application/json;charset=UTF-8'
    // 如果存在token值就添加进Authorization
    if (store.state.token) {
      config.headers.Authorization = store.state.token
    }
    // 发送请求
    return config
  },
  error => {
    return Promise.reject(error)
  }
)
// 响应拦截 下面具体根据实际接口配置
service.interceptors.response.use(
  response => {
    closeLoading()
    console.log('response', response)
    const res = response.data
    if (res && res.code === 10000) {
      return res.data// 封装好可直接返回data
    } else if (res.code === 10001) {
      Message({
        message: res.message,
        type: 'warning',
        duration: 3000
      })
      return Promise.reject(res.message || '后端服务错误')// 因为此时是收到了后端的接口数据  Promise.reject(res)返回一个被res原因拒绝的promise对象
    } else if (res.status === 403) {
      Message({
        message: '登录失效,请重新登录',
        type: 'error',
        duration: 3000
      })
      // 清除cookie信息
      store.commit('updateToken', '')
      window.location.href = '#/login'
      return 1
    } else {
      // 处理execl
      return response.data
    }
  },
  // 登陆接口可以配合js-cookie或者localstorage进行token的保存,在未登出的情况下结合路由守卫直接进入home页
  // 在后台token失效时的逻辑,此时因为cookie中有token,所以路由守卫不会拦截,还是会进入home页面,但如果在home页面请求其他接口时判断发给后台的token,如果已经失效,后台令403为登陆失效的信息,前端清除cookie与state中的token值
  // 如果没有token值,则路由守卫会作出处理,直接进入login页面
  error => {
    closeLoading()
    if (error.response.status === 403) {

    } else {

    }
    return Promise.reject(error.response)
  }
)
export default service

b.在main.js中进行全局的引入

image.png

c.在具体组件中进行调用

   async loginForm () {
      // 一定注意请求方式
      const data = await this.axios.get('/api/login', {
        params: {
          name: this.ruleLogin.name,
          password: this.ruleLogin.password
        }
      })
      this.$store.commit('updateToken', data)
      this.$router.push('/')
    },
 //post请求  this.axios.post('...',data)
 //上传下载文件时,如果要求确定接口参数形式,比如responseType,形式如下所示
 const data = await this.axios.get('/api/getName', {
        params: this.request,
        // 一定要加上这句
        responseType: 'blob'
 })

2.开发环境与生产环境跨域的配置

a.开发环境:使用反向代理,服务器之间不存在跨域问题,如果请求的链接不存在,则会返回本地index文件的内容。

配置目录 /config/index.js
proxyTable: {
  '/apis':{//以apis开头的url才会进行接口转发
    target: 'http://10.1.63.26:19080/',  // 后台api
    changeOrigin: true,  //是否跨域
    // secure: true,
    pathRewrite: {
      '^/apis': ''   //需要rewrite的
    }
  }
}

或者使用浏览器中的插件

image.png

b.生产环境:需要后端开启跨域 打包之后部署到服务器要去除/apis,才能正常访问后台接口

axios的默认实例有一个baseURL的属性

axios.defaults.baseURL='/apis'
axios.get('/user')  //访问/user就相当于访问 http://localhost:8080/apis/user

axios.defaults.baseURL='https://abc.com'
axios.get('/user')  //访问/user就相当于访问 https://abc.com/user
//process.env.NODE_ENV用于区分是生产环境还是开发环境
//配置不同的baseURL
baseURL: process.env.NODE_ENV === 'production' ? 'http://abc.com:8888/' : '/apis'
这样配置之后,打包部署到服务器上也不用再手工去除/apis

补充:

1.存在多个请求路径

可以配置多个axios,分别在全局引入

2.可在api.js中对接口完成统一维护

参考链接

//可在src下新建api.js文件夹,引入封装好的axios,然后在需要调用的地方直接引入
import axios from '../apiconfig/index';

export defalue {
    //GET请求
    fetchData1 = query => {
        return request({
            url: '/table1.json',
            method: 'get',
            params: query
        });
    };
    //POST请求
    fetchData2 = query => {
        return request({
            url: '/table2.json',
            method: 'post',
            data: query
        });
    };
    //delete、put请求同get的写法
}