vue学习过程总结(07) - vue的后台服务API封装及跨域问题的解决

以登录流程为例说明接口的封装。

1.登录调用后台的登录api

登录界面的代码

<template>
  <div class="login-page">
    <div class="login-container">
      <div class="login-title">后台管理系统</div>
      <el-form
        ref="loginForm"
        :model="loginForm"
        :rules="rules"
        auto-complete="on"
        label-position="left"
        class="login-form"
      >
        <el-form-item prop="username">
          <el-input
            prefix-icon="el-icon-s-custom"
            v-model="loginForm.username"
            placeholder="用户名"
            name="username"
            type="text"
            tabindex="1"
            auto-complete="off"
          />
        </el-form-item>

        <el-form-item prop="password">
          <el-input
            prefix-icon="el-icon-lock"
            type="password"
            v-model="loginForm.password"
            placeholder="密码"
            name="password"
            tabindex="2"
            auto-complete="off"
            @keyup.enter.native="submitForm()"
          />
        </el-form-item>
        <div class="login-btn">
          <el-button :loading="loading" type="primary" @click="submitForm()">登录</el-button>
        </div>
        <p class="login-tips">Tips : 一条小尾巴。。。</p>
      </el-form>
    </div>
  </div>
</template>

<script>
import { vuetest } from '@/api/index'

    var validateUsername = (rule, value, callback) => {
        console.log(value);
        if (value == undefined || value === "") {
            callback(new Error("请输入用户名"));
        } else {
            callback();
        }
    };
    var validatePassword = (rule, value, callback) => {
        if (value == undefined || value === "") {
            callback(new Error("请输入密码"));
        } else {
            callback();
        }
    };

export default {
  name: "Login",
  data() {
    return {
      loginForm: {
        username: "admin",
        password: "111111"
      },
      rules: {
        username: [
          { required: true, trigger: "blur", validator: validateUsername }
        ],
        password: [
          { required: true, trigger: "blur", validator: validatePassword }
        ]
      },
      loading: false
    };
  },
  methods: {
    submitForm() {
      this.$refs.loginForm.validate(valid => {
        if (valid) {
          this.loading = true;
          // 方法后台验证登录信息,验证成功后
          vuetest().then(res => {
            console.log("===============vue test===========");
            console.log(res);
            console.log(res.data.status);
            console.log(res.data.token);
            
            var tk = res.data.token;
            this.$store.dispatch("user/login", this.loginForm).then(() => {
              this.$store.dispatch("user/setTokenStore", tk);
            // 信息成功存储在vuex后跳转页面
            this.$router.push("/home");
            this.loading = false;
          });
            // this.$router.push("/home");
            // this.loading = false;
          }).catch(error => {
            console.log("===============vue test error===========");
            console.log(error);
          })
          // 将用户信息报存在vuex中
          // this.$store.dispatch("user/login", this.loginForm).then(() => {
          //   // 信息成功存储在vuex后跳转页面
          //   this.$router.push("/home");
          //   this.loading = false;
          // });
        //this.$router.push("/home");
        //localStorage.setItem('ms_username', this.loginForm.username);
        } else {
          this.$message.error("登录异常");
          return false;
        }
      });
    }
  }
};
</script>

2.请求api的封装

import { vuetest } from '@/api/index'  --- 引用src/api/idex.js文件中的export的vuetest 请求。src/api/idex.js中有请求方式、请求参数等设置

vuetest().then(res => {  ----- res请求服务端接口返回的数据

src/api/idex.js文件代码

// api封装示例

// 导入配置好的axios文件
import Axios from "@/axios" 


// 封装axios请求函数,并用export导出
export function getItemList(datas) {
    return Axios({
    url: "/api/getItemList",
    method: "post",
    headers: {
        'Content-Type': 'application/x-www-form-urlencoded' //设置请求头请求格式form
    },
    data: datas
    })
}
export function getItem(datas) {
    return Axios({
    url: "/api/getItem",
    method: "post",
    headers: {
        'Content-Type': 'application/json' //设置请求头请求格式为json
    },
    data: datas
    })
}

export function getItemInfo(datas) {
    return Axios({
    url: "/api/getItemInfo"+datas,
        method: "get",
    })
}

export function vuetest(datas) {
    return Axios({
    url: "/vue/test",
    method: "post",
    headers: {
        'Content-Type': 'application/json' //设置请求头请求格式为json
    },
    data: datas
    })
}

说明:

调用最后一个函数,专注于请求参数的处理。

return Axios({ ----- 是ajax请求的处理,Axios是import Axios from "@/axios"中导出的对象

3.ajax请求的进一步封装,主要是对所有ajax请求的一些共同的参数的设定,如超时时间、根路径

src/axios中的index文件(这个index.js文件的名字应该是不能改变的,所有导入的路径没有确定到文件而是目录)

//引入 axios库
import axios from 'axios'
//引入 node中自带的qs模块(数据格式转换)
import qs from 'qs'

/* 2.全局默认配置 */
let baseURL
// 判断开发环境(一般用于本地代理)
// if (process.env.NODE_ENV === 'development') { // 开发环境
//     baseURL = 'http://localhost:8082/VoucherWebService'   // 你设置的本地代理请求(跨域代理),下文会详细介绍怎么进行跨域代理
// } else {               // 编译环境
//     if (process.env.type === 'test') {    // 测试环境
//         baseURL = 'http://sw.apitest.com'
//     } else {                              // 正式环境
//         baseURL = 'http://sw.api.com'
//     }
// }

// 配置axios的属性
axios.defaults.timeout = 6000;    // 请求超时时间1分钟                  
//axios.defaults.baseURL = baseURL; // 你的接口地址 
axios.defaults.responseType = "json";
axios.defaults.withCredentials = false;  //是否允许带cookie这些
 
/*你也可以创建一个实例,然后在实例中配置相关属性,此方法和上面的方法一样,写法不同,怎么用随个人
*喜好,我比较喜欢用这种方法,如下:
*/
const Axios = axios.create({
    baseURL:baseURL ,               // 后台服务地址
    timeout: 60000,               // 请求超时时间1分钟
    responseType: "json",
    withCredentials: false    // 是否允许带cookie这些
});
 
/* 3.设置拦截器 */  
/*如果不是用创建实例的方式配置,那么下面的Axios都要换成axios,也就是文件开头你用import引入axios
时定义的变量*/
Axios.interceptors.request.use((config) => {
    // 发送请求前进行拦截
    // 可在此处配置请求头信息
    // config.headers["appkey"] ="...";
  // config.headers["token"] ="...";
  console.log("======interceptors=====");
  console.log(config);
     if (config.method == "post") {
  /*数据转换: axios post方式默认是json格式提交数据,如果使用application/x-www-form-urlencoded数据格式提交,要用qs.stringify()进行转换,个人建议不在拦截器中全局配置,因为不够灵活,还有一点是,如果
设置了重新请求的配置,那么重新请求时,请求体中的config里面的传参就会被再次进行qs.stringify()转
换,会使得参数丢失,造成请求失败。*/
         config.data = qs.stringify(config.data)
     }
    return config;
  },(error) =>{
    //console.log("错误的传参", 'fail');
    return Promise.reject(error)
  })

// Axios.interceptors.response.use((res) =>{
//    // 请求响应后拦截
//    if(res.status == 200){                       // 对响应数据做些事
//        //alert("提交成功")
//        return Promise.resolve(res)
//     }
//     return res;
//  }, (error) => {  
//    //alert("网络异常!") 404等问题可以在这里处理
//    return Promise.reject(error)
//  })
export default Axios 

如果浏览器报这个错:: No 'Access-Control-Allow-Origin' header 

这是个跨域问题:client/server同一个ip不同端口或者相同的端口不同的ip或者ip、端口都不同(个人理解)

vue-cli2解决方法(3.x网上也有),在

config/index.js文件中的proxyTable添加如下配置:

  proxyTable: {
      '/': {
            target: 'http://localhost:8082/myproject', //你要访问的服务器域名
            changeOrigin: true, //允许跨域
            pathRewrite: {
                '^/': ''
            }
        }

    },

 axios中的baseURL 不能配置否则就不用这个代理的配置了。

posted @ 2019-12-06 17:21  话祥  阅读(675)  评论(0编辑  收藏  举报