目录
1、网络请求
2、项目实战应用
项目中使用 axios 进行网络请求,Vue 脚手架默认没有安装,需要自行安装才能使用。
- 安装 ( 生产环境依赖 ) "axios": "^0.24.0"
npm i -S axios
- 设置统一请求域名
- 反向代理 可以进行 跨域 解决
在项目根目录下面创建一个 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' } } } } }
代理配置 :
这里 , 此处 配置 反向代理 文件内 会有一个 小坑 :
因为 匹配 的 规则 为 express.use 模糊匹配 , 匹配成功后就会停止向下匹配了 ,
所以匹配的 请求前缀 尽量 不要一样 ,
比如 你写的 ' / api ' , 只要你的请求地址内存在 / api , 它在匹配上之后就会走对象内的程序代码了 , 就不会再向下执行 ,
所以为了预防此问题 , 所以 最好是把 你的 请求前缀 改成 ' ^/api ' ( 以 /api 开头的 )
这样的写法会更严谨 , 防止模糊匹配钻了漏洞
否则即使你下面 再怎么写的 pathRewrite ( 路径重写 ) , 也会失去效果 , 将你的重写路径依旧会带在你的请求地址里 , 并没有给过滤掉 , 导致请求一直 404 失败
所以 , 我们一是要注意咱们的 请求前缀不要一样 ,
二就是我们 最好 将前缀的写法写的更加严谨一些
网络请求模块化 :
关于 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
项目 / 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
暂无数据
加载中 ...
已加载全部