(精华)2020年7月13日 vue axio.js封装和环境配置

一、 axios的封装

1.1在src根目录 新建providers文件 ,以及添加几个主要的 文件

|—providers
|-----util.js 工具函数
|-----api.js 接口地址
|-----axios.js 封装axios的文件

mkdir providers
touch util.js api.js axios.js

1.2 配置工作环境 (dev,test,build)

安装:
yarn add cross-env -D

在package.json里配置:
"scripts": {
    "test":"cross-env scene=test webpack --config webpack.config.js",
    "dev":"cross-env scene=dev webpack-dev-server --config webpack.config.js",
    "build":"cross-env scene=prod webpack --config webpack.config.js"
    },

在配置文件webpack.config.js通过内置插件DefinePlugin配置
var webpack = require('webpack');

    plugins.push(new webpack.DefinePlugin({
        'sceneParam': JSON.stringify(process.env.scene),
        'laney':JSON.stringify('laney'),
        'test':'"kkkkk"'
    })); 

重新启动就可以在项目中直接获取到 sceneParam 参数

1.3 添加登陆页面 pages/login.vue

参照:Element ui Form表单
https://element.eleme.cn/#/zh-CN/component/form

校验利用策略模式, 和es5里的form表单验证思想一致
校验成功后, 调取登陆接口

submitLogin(){
        var {pass,username} = this.ruleForm
        axios({
            method:'post',
            url:'http://localhost:8081/api/login',
            data:{
                name:username,
                password:pass
            }
        }).then((res)=>{
            
            if(res.data.statusCode==200) {
                 alert(res.data.data);
                 localStorage.setItem('token',res.data.token); //用户访问页面的钥匙
                 
                 this.$router.push({
                     path:'/home'
                 });
            } else {
                 alert(res.data.data);
            }
           
        });
           
    }

1.3 在home.vue页面调取相关接口 ,如何处理接口的多级回调

pages/home.vue

export default {
    data(){
        return {
            name:'laney',
            params:this.$route.query,
            infoData:{}
        }
    },
    methods:{
        getInfoList(){
            var token = localStorage.getItem('token');
            var test = {name:'laney',age:'20'}
            var mn = Qs.stringify(test);
            // this.$axios.post('http://localhost:8081/api/info',mn).then((res)=>{
            //     console.log('test kkkk-----------');
            // })
             this.$axios({
                method:'post',
                url:'http://localhost:8081/api/info',
                data:mn,
                headers:{
                    token:token
                }
            }).then((res)=>{
                if(res.data.statusCode==200) {     
                     this.infoData = res.data.result;
                     var tag = res.data.tag;
                     return this.$axios({
                            method:'post',
                            url:'http://localhost:8081/api/msg'
                        })
                } else {
                     alert(res.data.result);
                }
            }).then((res)=>{
                console.log(res.data.result)
            });
        }
    },
    mounted(){
        this.getInfoList();
    }
}
</script>

1.4 配置api

export default {
    basic:{
        login:'/api/login',
        info:'/api/info',
        msg:'/api/msg',
        hello:'/api/hello'

    }
}

1.5 在入口文件main.js进行引入

 import axios from './providers/axios.js';
 import api from './providers/api.js';
 //定义全局变量$axios
 Vue.prototype.$axios = axios;
 Vue.prototype.$api = api;

1.6 配置axios

yarn add axios -D , 已安装的可以忽略
引入axios 
import axios from 'axios';

导出的结构是:
export default {
  post, //方法名
  get,
  pull
}
封装的目的:
1.需要把一些 api 的base路径配置好,以免多次重复写入
2.项目可能传递给接口的 数据 有json 和 formData 都需要考虑
3.对登陆后可能权限的 token需要获取 统一设置
4.对接口异常的情况需要统一处理

1.6.1 第一种方式, 利用拦截器配置headers

后面讲

1.6.2 第二种方式, 不利用拦截器配置headers

整体思路是在传参的时候, 可以多加一个参数form(true,false), true代表需要formData , false或者不选代表json
参考: axios2.js

var typearr= {
  'json':'application/json;charset=UTF-8',
  'form':'application/x-www-form-urlencoded'
};
  post (url, params) {
      var isForm = params.form;
      if(params.form)  {
        delete params.form;
      }
      if(isForm) {
        params = Qs.stringify(params);
      }

    return new Promise((resolve,reject) => {
       return axios.post(url,params, {
          headers: {
            'X-API-TOKEN':localStorage.getItem('token'),
            'Content-Type': isForm ? typearr['form'] : typearr['json'],
            'test':'ppp'
          }
      })
        .then(response => {
          if(response.status==200){
             resolve(response.data);
          } 
          //这里不需要异常提示了, 已经在拦截器设置
          // else {
          //   Message({
          //     message: response.errorMsg,
          //     type: 'warning'
          //   });
          // }
        })
        .catch(err => {
          reject(err)
        })
      })
  },

1.7在页面中使用

以news.vue为例

 <script>
export default {
    data(){
        return {
            infoData:{}
        }
    },
    methods:{
        getInfoList2(){
            var res = this.$axios.post(this.$api.basic.info,{
                kind:'school',
                form:true
            }).then((res)=>{  
                console.log(res);
            });
        },
        
        getInfoList(){
          this.$axios.post(this.$api.basic.info,{
              kind:'school'
          },'form').then((res)=>{
              this.infoData = res.result;
                if(res.tag==1){
                    return  this.$axios.post(this.$api.basic.msg,{
                        tag:res.tag
                    })
                }
          }).then((res)=>{
              if(res.kind==2){
                    return  this.$axios.post(this.$api.basic.hello,{
                        id:res.kind
                    })
              }
          }).then((res)=>{
              console.log(res.result);
          })
  
        }
    },
    mounted(){
        this.getInfoList2();
        // this.getInfoList();
        
    }
}
</script>

1.8 拦截器的处理以及异常处理

var formData = new FormData();
formData.append('name','song');
formData.get('name');

//http request 拦截器  你给服务端 的数据 
axios.interceptors.request.use(
  config => {   
    config.headers.common = {
      'X-API-TOKEN': localStorage.getItem('token'),
      'version': '1.0',
      'Content-Type': 'application/json;charset=UTF-8'
    }
    console.log('begin');
    if (config.data.form) {
        //转化成formData格式
        // transformRequest只能用在 PUT, POST, PATCH 这几个请求方法
        config.transformRequest=[function (data) {
            //方式一
            data.name='laney';
            delete data.form;
            var ret = '';
            for (let it in data) {
              ret += it+'=' +data[it] + '&';
            }
            return ret.substring(0,ret.length-1);

            //方式二:
            // var test2 = Qs.stringify(data);
            // return test2;
          }]
        }

    return config;
  },
  error => {
    return Promise.reject(err);
  }
);

//响应拦截器即异常处理 -  -- 服务给我们的数据
axios.interceptors.response.use(response => {
    
    if (response.status === 200) {
        return Promise.resolve(response);
    } else {
        return Promise.reject(response);
    }
    // return response
}, err => {
    if (err && err.response) {
      switch (err.response.status) {
        case 400:
            console.log('错误请求')
          break;
        case 401:
            console.log('未授权,请重新登录')
          break;
        case 403:
          console.log('拒绝访问')
          break;
        case 404:
          console.log('请求错误,未找到该资源')
          break;
        case 405:
          console.log('请求方法未允许')
          break;
        case 408:
          console.log('请求超时')
          break;
        case 500:
          console.log('服务器端出错')
          break;
        case 501:
          console.log('网络未实现')
          break;
        case 502:
          console.log('网络错误')
          break;
        case 503:
          console.log('服务不可用')
          break;
        case 504:
          console.log('网络超时')
          break;
        case 505:
          console.log('http版本不支持该请求')
          break;
        default:
          console.log(`连接错误${err.response.status}`)
      }
    } else {
      console.log('连接到服务器失败')
    }
    return Promise.resolve(err.response)
})

然后开始封装函数

export default {
  /**
   * 封装post方法
   * @param url
   * @param data
   * @returns {Promise}
   * 
   */
// 方式一: 包装一个 new Promise
  // post (url, params) {
  //   return new Promise((resolve,reject) => {
  //      return axios.post(url,params)
  //       .then(response => {
  //         if(response.status==200){
  //            resolve(response.data);
  //         } else {
  //           alert(response.errorMsg);
  //         }
  //       })
  //       .catch(err => {
  //         reject(err)
  //       })
  //     })
  // },
// 方式二: 包装一个 直接利用axios自身是一个Promise对象的思想封装
  // post (url, params) {
  //      return axios.post(url,params)
  //       .then(response => {
  //         if(response.status==200){
  //           return Promise.resolve(response.data); 
  //           //注意必须要有return,相当于new Promise里的resolve,告诉接口已经获取数据
  //         } else {
  //           alert(response.errorMsg);
  //         }
  //       })
  //       .catch(err => {
  //         reject(err)
  //       })
  // },

//方式三
// 注意: axios在配置headers头的时候, 不要和上面的 拦截器重复配置
  post (url, params) {
      var isForm = params.form;
      if(params.form)  {
        delete params.form;
      }
      if(isForm) {
        params = Qs.stringify(params);
      }
      return axios({
        method: 'post',
        url:url,
        data: params
      }).then((response) => {
        
        if(response.status==200){
          return Promise.resolve(response.data)  
        } else {
          <!-- 如果设置了拦截器, 这里不需要做异常处理 -->
          alert(response.errorMsg);
        }
        },(e) => {
          return Promise.reject(e)
        }) 
        // 或者catch捕获异常
        .catch(function (error) {
          
        })
  },

//方式四:
// async post (url, params,contype) {
//     if(contype=='form'){
//       params = Qs.stringify(params);
//     }
//     var res = await axios({
//         method: 'post',
//         url:url,
//         data: params
//     });
//   return res.data;

// },

  get(url,params={}){
    return new Promise((resolve,reject) => {
      axios.get(url,{
        params:params
      })
      .then(response => {
        resolve(response.data);
      })
      .catch(err => {
        reject(err)
      })
    })
  },
}

1.9 异常消息提示

在axios.js里 添加
import { Message} from 'element-ui';

然后直接使用
Message({
      message: '提示信息',
      type: 'warning'
 });

整个axio.js文件

// 使用数据拦截器
import axios from 'axios';
import Qs from 'qs';
import {
  Message
} from 'element-ui';
axios.defaults.timeout = 5000;

// env_config
// dev  开发环境
// test  测试环境
// build  线上环境
var urlObj = {
  dev: 'http://localhost:8081',
  test: 'http://localhost:8081/',
  build: 'https://www.17npw.net/api/'
}
console.log(urlObj[sceneParam]);
// Message('这是一条消息提示');
axios.defaults.baseURL = urlObj[sceneParam]; //填写域名

//http request 拦截器  客户端给服务端 的数据 
axios.interceptors.request.use(
  config => {

    config.headers.common = {
      'X-API-TOKEN': localStorage.getItem('token'),
      'version': '1.0',
      'Content-Type': 'application/json;charset=UTF-8'
    }
    console.log('begin');

    if (config.data.form) {
      //转化成formData格式
      // transformRequest只能用在 PUT, POST, PATCH 这几个请求方法
      config.transformRequest = [function (data) {
        //方式一
        delete data.form;
        // var ret = '';
        // for (let it in data) {
        //   ret += it+'=' +data[it] + '&';
        // }
        // return ret.substring(0,ret.length-1);

        //方式二:
        var test2 = Qs.stringify(data);
        return test2;
      }]
    }

    return config;
  },
  error => {
    return Promise.reject(err);
  }
);

//响应拦截器即异常处理 -  -- 服务给客户端的数据进行处理
axios.interceptors.response.use(response => {
  if (response.status === 200) {
    return Promise.resolve(response);
  } else {
    return Promise.reject(response);
  }
  // return response
}, err => {
  if (err && err.response) {
    var errorMsg = '';
    switch (err.response.status) {
      case 400:
        console.log('错误请求')
        errorMsg = '错误请求';
        break;
      case 401:
        console.log('未授权,请重新登录');
        errorMsg = '未授权,请重新登录';
        break;
      case 403:
        console.log('拒绝访问')
        errorMsg = '拒绝访问';
        break;
      case 404:
        console.log('请求错误,未找到该资源')
        errorMsg = '请求错误,未找到该资源';
        break;
      case 405:
        console.log('请求方法未允许')
        errorMsg = '请求方法未允许';
        break;
      case 408:
        console.log('请求超时')
        errorMsg = '请求超时';
        break;
      case 500:
        console.log('服务器端出错')
        errorMsg = '服务器端出错';
        break;
      case 501:
        console.log('网络未实现')
        errorMsg = '请求方法未允许';
        break;
      case 502:
        console.log('网络错误')
        errorMsg = '网络错误';
        break;
      case 503:
        console.log('服务不可用')
        errorMsg = '服务不可用';
        break;
      case 504:
        console.log('网络超时')
        errorMsg = '网络超时';
        break;
      case 505:
        console.log('http版本不支持该请求')
        errorMsg = 'http版本不支持该请求';
        break;
      default:
        console.log(`连接错误${err.response.status}`)
    }

    Message({
      message: errorMsg,
      type: 'warning'
    });

  } else {
    console.log('连接到服务器失败')
  }
  return Promise.resolve(err.response)
})

export default {
  //post方法 
  //     post(url,params){
  //         return new Promise((resolve,reject)=>{
  //             return axios.post(url,params)
  //             .then((response)=>{
  //                 if(response.status==200){
  //                     resolve(response.data);
  //                 }

  //             })
  //         })

  //     },

  //     // 方式二: 包装一个 直接利用axios自身是一个Promise对象的思想封装
  //   post (url, params) {
  //        return axios.post(url,params)
  //         .then(response => {
  //           if(response.status==200){
  //             return Promise.resolve(response.data); 
  //             //注意必须要有return,相当于new Promise里的resolve,告诉接口已经获取数据
  //           } 
  //         })
  //         .catch(err => {
  //           reject(err)
  //         })
  //   },

  // //方式三
  // // 注意: axios在配置headers头的时候,会合并拦截器和函数封装里的headers的选项
  //   post (url, params) {
  //       return axios({
  //         method: 'post',
  //         url:url,
  //         data: params,
  //         headers:{
  //             'X-API-TOKEN':localStorage.getItem('token'),
  //             'Content-Type': isForm ? typearr['form'] : typearr['json'],
  //             'test':'ppp'
  //       }
  //       }).then((response) => {

  //         if(response.status==200){
  //           return Promise.resolve(response.data)  
  //         } 
  //         },(e) => {
  //           return Promise.reject(e)
  //         }) 
  //         // 或者catch捕获异常
  //         .catch(function (error) {

  //         })
  //   },
  //方式四:
  async post(url, params) {
    var res = await axios({
      method: 'post',
      url: url,
      data: params
    });
    return res.data;

  },

  /**
   * 封装patch请求
   * @param url
   * @param data
   * @returns {Promise}
   */

  patch(url, data = {}) {
    return new Promise((resolve, reject) => {
      axios.patch(url, data)
        .then(response => {
          resolve(response.data);
        })
    })
  },

  get(url, params = {}) {
    return new Promise((resolve, reject) => {
      axios.get(url, {
          params: params
        })
        .then(response => {
          resolve(response.data);
        })
    })
  },
}

©️2020 CSDN 皮肤主题: 猿与汪的秘密 设计师:上身试试 返回首页