axios 数据请求二次封装及实战案例

目录

1、网络请求

2、项目实战应用


1、网络请求

项目中使用 axios 进行网络请求,Vue 脚手架默认没有安装,需要自行安装才能使用。

  • 安装 ( 生产环境依赖 )  "axios": "^0.24.0"

 npm i -S axios 

  • 设置统一请求域名

axios 数据请求二次封装及实战案例_第1张图片

  • 反向代理 可以进行 跨域 解决

在项目根目录下面创建一个 vue.config.js 文件,写下如下代码

Vue 之 vue.config.js 配置文件_Mr.小灰狼_随笔-CSDN博客_vue.config.js

module.exports = {
  devServer: {
    overlay: false,
    // vue 项目代理请求
    proxy: {
      // 规则
      // axios 中相对地址开头的字符串
      '/api': {
        // 把相对地址中的域名 映射到 目标地址中
        // localhost:8080 => localhost:3000
        target: 'http://localhost:3000',
        // 修改 host 请求的域名为目标域名
        changeOrigin: true,
        // 请求 uri 和目标 uri 有一个对应关系
        // 请求 /api/login ==> 目标 /v1/api/login
        pathRewrite: {
          '^/api': '/v1/api'
        }
      }
    }
  }
}

axios 数据请求二次封装及实战案例_第2张图片

代理配置 :

axios 数据请求二次封装及实战案例_第3张图片

axios 数据请求二次封装及实战案例_第4张图片

这里 , 此处 配置 反向代理 文件内 会有一个 小坑 : 

因为 匹配 的 规则 为  express.use  模糊匹配 , 匹配成功后就会停止向下匹配了 ,

所以匹配的 请求前缀 尽量 不要一样 ,  

比如 你写的  ' / api '   ,  只要你的请求地址内存在  / api  , 它在匹配上之后就会走对象内的程序代码了 , 就不会再向下执行 , 

所以为了预防此问题 , 所以 最好是把 你的 请求前缀 改成  ' ^/api '  ( 以 /api 开头的 )

这样的写法会更严谨 , 防止模糊匹配钻了漏洞

否则即使你下面 再怎么写的 pathRewrite ( 路径重写 ) , 也会失去效果 , 将你的重写路径依旧会带在你的请求地址里 , 并没有给过滤掉 , 导致请求一直 404 失败

所以 , 我们一是要注意咱们的 请求前缀不要一样 ,

二就是我们  最好 将前缀的写法写的更加严谨一些 

axios 数据请求二次封装及实战案例_第5张图片

axios 数据请求二次封装及实战案例_第6张图片

 网络请求模块化 : 

axios 数据请求二次封装及实战案例_第7张图片

axios 数据请求二次封装及实战案例_第8张图片

axios 数据请求二次封装及实战案例_第9张图片

axios 数据请求二次封装及实战案例_第10张图片

axios 数据请求二次封装及实战案例_第11张图片


关于 axios 中设置 axios.defaults.withCredentials 的问题

withCredentials : 默认 情况下 ,跨源 请求 不提供 凭据

( cookie 、HTTP 认证 及 客户端 SSL 证明 等 ) 。

通过将 withCredentials 属性 设置 为 true ,可以指定某个请求应该发送凭据 。

默认值 为 false 。不提供
true  : 在跨域请求时 ,会 携带用户凭证
false :在跨域请求时 ,不会 携带用户凭证 ;返回的 response 里也会忽略 cookie
当配置了 withCredentials = true时 ,

必须 在 后端 增加  response  头信息  Access-Control-Allow-Origin  ,

且必须 指定 域名 ,而不能 指定 为  *

如果 后端 需要 带  cookie  过去 , 前端需要设置为  true

axios 数据请求二次封装及实战案例_第12张图片


2、项目实战应用

二次封装 axios

项目  /  src  /  utils  /  request.js

// 导入 axios
import axios from "axios";
import { Message } from "element-ui";
// import env from '@/config/environment'
import Vue from "vue";

// 全局的 axios 默认值
// 设置请求的基础域名
// axios.defaults.baseURL = process.env.DW_API_URL
// axios.defaults.baseURL = baseurl
// 请求超时时间
axios.defaults.timeout = 10000;
// 在跨域请求时,会携带用户凭证( 是否允许请求携带 Cookie )
axios.defaults.withCredentials = true; // 后端需要带 cookie 过去

// post 请求头
// axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8'

console.log(process.env, "VUE_APP_URL");
const service = axios.create({
  // baseURL: process.env.NODE_ENV === 'production' ? process.env.VUE_APP_BASE_API : 'api',  // api 的 base_url
  // baseURL: '/dev-api/', 设置基础路径
  // axios 中请求配置有 baseURL 选项,表示请求 URL 公共部分
  // baseURL: process.env.VUE_APP_BASE_URL,    // url = base url + request url
  // baseURL: baseurl,
  // 请求超时时间
  // timeout: env.envTimeout,
  timeout: 10000, // request timeout 设置最大响应时间,10秒
});

// request 请求拦截器
service.interceptors.request.use(
  (config) => {
    config.headers["Content-Type"] = "application/json";
    console.log(config, "config");
    // config.timeout = 10000
    return config;
  },
  (error) => {
    // 请求失败拦截
    console.log("request-error:" + error); // for debug
    return Promise.error(error);
  }
);

// response 响应拦截器
service.interceptors.response.use(
  (response) => {
    if (response.status === 200) {
      return response.data;
    } else {
      return Promise.reject(response);
    }
  },
  (error) => {
    // 服务器状态码不是200的情况
    let { message } = error;
    if (message.includes("Network Error")) {
      message = "后端接口连接异常";
    } else if (message.includes("timeout")) {
      message = "系统接口请求超时";
    } else if (message.includes("Request failed with status code")) {
      const code = message.substr(message.length - 3);
      if (code === "401" || code === "403") {
        message = null;
        if (code === "401") {
          // 401 表示没有权限(令牌, 用户名, 密码错误)
          // msgBoxNoLogin();
        } else if (code === "403") {
          // 403 表示用户有权限, 只是访问时被禁止的(可以理解为, 用户有权限, 但是某些目录禁止访问)
          // msgBoxNoRole();
          message = "您没有权限访问该目录"
        }
      } else {
        message = "系统接口" + message.substr(message.length - 3) + "异常";
        console.log(message, 'message');
      }
    }
    if (message !== null) {
      Message.error({
        message: message,
      });
    }
    return Promise.reject(error);
  }
);

// response 响应拦截器
/* service.interceptors.response.use(
  (response) => {
    console.debug("response");
    console.debug(response);
    if (response.status === 200) {
      const { data } = response;
      if (data.hasOwnProperty("resultCode")) {
        if (data.resultCode === 401) {
          msgBoxNoLogin();
        } else if (data.resultCode === 403) {
          msgBoxNoRole();
        } else if (data.resultCode !== 200) {
          let message = `异常码:${data.resultCode}`;
          if (data.hasOwnProperty("resultMsg")) {
            message = `${data.resultMsg},异常码:${data.resultCode}`;
          }
          msgError(message);
        }
      }
      return Promise.resolve(response);
    } else {
      return Promise.reject(response);
    }
  },
  (error) => {
    // 服务器状态码不是200的情况
    console.log("err" + error);
    let { message } = error;
    if (message.includes("Network Error")) {
      message = "后端接口连接异常";
    } else if (message.includes("timeout")) {
      message = "系统接口请求超时";
    } else if (message.includes("Request failed with status code")) {
      const code = message.substr(message.length - 3);
      if (code === "401" || code === "403") {
        message = null;
        if (code === "401") {
          msgBoxNoLogin();
        } else if (code === "403") {
          msgBoxNoRole();
        }
      } else {
        message = "系统接口" + message.substr(message.length - 3) + "异常";
      }
    }
    if (message != null) {
      msgError(message);
    }
    return Promise.reject(error);
  }
); */

// Vue.prototype.$http = service;

// export default service;

/**
 * 封装后的 get 请求方法
 * @param {string} url 请求路径
 * @param {object} data 请求参数
 * @param {object} params 用户自定义设置(参数)
 * @returns
 */
// GET 请求方法
export const get = (url, params = {}) => {
  let str = "?";
  Object.keys(params).forEach((item) => {
    str += `${item}=${encodeURI(params[item])}&`;
  });
  str = str.slice(0, -1);
  return service.get(url + str);
};

// POST 请求方法
export const post = (
  url,
  data = {},
  config = {
    headers: {
      "Content-Type": "application/json",
    },
  }
) => service.post(url, data, config);

模块化拆分

项目  /  src  /  config  /  api  /  listConfig.js

/* 网络 api 接口的基础配置 */
// 网络请求 的 地址信息
export default {
  getMattersList: '/api/survey/surveylist',    // 列表页所有事项数据
  saveSurveyName: '/api/surveyDesign/xxxx',    // 保存问卷名称
  saveAllQuestion: '/api/xxxxxxx/xxxxxxxx',    // 新建保存接口(全部)
  selectSurveyDetial: '/xxx/xxxxxxx/xxxxx',    // 预览
  xxxxXxxxxx: 'xxxxxxx/xxxxxxxxxx/xxxxxxx',    // XXXXXXXX
  
}

项目  /  src  /  config  /  environment.js

/ *  网站环境配置  * /

export default {

    envTimeout :  10000 , 

}


项目  /  src  /  api  / listApi.js

/* 网络 api 接口 */
// 请求网络方式
// 导入封装好的方法
import { get, post } from '../utils/request'
// 导入网络请求的地址信息
import config from '../config/api/listConfig'

// 首页问卷事项列表
export const getMyListApi = async (data) => await post(config.getMyList, data)
// 详情
export const getAnswerApi = async (params) => await get(config.getAnswer, params)
// 提交接口
export const saveAnswerApi = async (data) => await post(config.saveAnswerApi, data)
// 所有事项数据
export const getListApi = async (data) => await post(config.getList, data)
// 场景共享数据
export const getModelListApi = async (data) => await post(config.getModelList, data)

/* // 首页问卷事项列表
export const getMySurveylistApi = async (data) => {
  let ret = await post(config.getMySurveylist, data)
  return ret
}
// 首页 => 问卷详情
export const getExcuteAnswerApi = async (params) => {
  let ret = await get(config.getExcuteAnswer, params)
  return ret
}
// 问答页提交接口
export const saveAnswerApi = async (data) => {
  let ret = await post(config.saveAnswerApi, data)
  return ret
}
// statisticalManagement_所有事项数据
export const getSurveylistApi = async (data) => {
  let ret = await post(config.getSurveylist, data)
  return ret
}
// statisticalManagement_场景共享数据
export const getModelSurveylistApi = async (data) => {
  let ret = await post(config.getModelSurveylist, data)
  return ret
} */

Vue 组件内使用

 项目  /  src  /  views  /  home  /  index.vue





你可能感兴趣的:(前端,Ajax,前端)