qs使用方式+axios

  • 背景
    • 技能列表
      • qs.parse()将 URL 解析成对象的形式
      • qs.stringify()将对象序列化成 URL 的形式
      • 传递数组的几种方式
        • 带索引的模式(默认模式)
        • 不带索引
        • arrayFormat 形式格式化
        • 扩展封装(对应后台的接收方式)
      • 整体代码
      • uni-app + qs
        • 安装 qs
        • 基础公共封装

背景

前端传参的时候。一般会用到 axios 或者 fetch 、Ajax 。 fetch 、 axios 慢慢从其中崛起。 qs 实在配合这些 api 时,使用最多的参数格式化工具。

qs官网

技能列表

qs.parse()将 URL 解析成对象的形式

优秀的文章-详解qs

qs.stringify()将对象序列化成 URL 的形式

优秀的文章-详解qs

传递数组的几种方式

带索引的模式(默认模式)

qs.stringify({ a: ['b', 'c', 'd'] });
// 'a[0]=b&a[1]=c&a[2]=d'

不带索引

qs.stringify({ a: ['b', 'c', 'd'] }, { indices: false });
// 'a=b&a=c&a=d'

arrayFormat 形式格式化

qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'indices' })
// 'a[0]=b&a[1]=c'
qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'brackets' })
// 'a[]=b&a[]=c'
qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'repeat' })
// 'a=b&a=c'

扩展封装(对应后台的接收方式)

  • 后端从 Form Data 中获取参数
/*** 通用查询* @param url* @param data* Form Data 形式pageNum: 1pageSize: 20* @returns {Promise<unknown>}*/
export const axiosCommonFindPage = ({url, data}) => {return new Promise((resolve, reject) => {$axios({url,data,method: 'post',header: formDataHeader,transformRequest: [function (data) {// Do whatever you want to transform the datareturn qs.stringify(data, {arrayFormat: 'brackets'});}],}).then((res) => {resolve(res);}).catch(err => {reject(err);})})
};
  • 后端从 Form Data 中获取多层嵌套对象参数
/*** 通用保存编辑* @param url* @param data* Form Data 形式*      name: 24*      ip: 24*      port: 24*      maxClientNum: 24*      gpuNum: 24**** stringify* qs.stringify({ a: { b: { c: 'd', e: 'f' } } });// 'a[b][c]=d&a[b][e]=f'也可以设置为  dots notationqs.stringify({ a: { b: { c: 'd', e: 'f' } } }, { allowDots: true });// 'a.b.c=d&a.b.e=f'* @returns {Promise<unknown>}*/
export const axiosCommonSave = ({url, data}) => {return new Promise((resolve, reject) => {$axios({url,data,header: formDataHeader,method: 'post',transformRequest: [function (data) {// Do whatever you want to transform the datareturn qs.stringify(data,{ allowDots: true })}],}).then((res) => {resolve(res);}).catch(err => {reject(err);})})
};
  • 后端 @RequestParam(“ids”) String[] ids
/*** 通用删除* 对应后端接收参数的形式 @RequestParam("ids") String[] ids* @param url* @param data* Form data 形式* ids: 40288192722a6bb401722ae5f6520007* ids: 4028819272276694017227674fa30003* @returns {Promise<unknown>}*/
export const axiosCommonBatchDelete = ({url, data}) => {return new Promise((resolve, reject) => {$axios({url,data,method: 'post',header: formDataHeader,transformRequest: [function (data) {// Do whatever you want to transform the datareturn qs.stringify(data,{indices:false});}],}).then((res) => {resolve(res);}).catch(err => {reject(err);})})
};
  • 后端 RequestParam(“ids[]”) String[] ids
/*** 对应后端接收参数的形式 RequestParam("ids[]") String[] ids* @param url* @param data* Form Data形式* ids[]  40288192722a980a01722a9ee6420000* ids[]  40288192722a980a01722a9f198e0001* @returns {Promise<unknown>}*/
export const axiosBatchDeleteForArrayBrackets = ({url, data}) => {return $axios({url,method: 'post',header: formDataHeader,data,transformRequest: [function (data) {// Do whatever you want to transform the data// brackets 括号的意思return  qs.stringify(data, {arrayFormat: 'brackets'});}],})
};

整体代码

import axios from 'axios';
import config, {formDataHeader} from './config';
import Cookies from "js-cookie";
import router from '@/router'
import {Message} from 'element-ui'
import * as login from './moudules/login'
import qs from "qs";// 使用vuex做全局loading时使用
// import store from '@/store'export default function $axios(options) {return new Promise((resolve, reject) => {let currentOptions = Object.assign({}, config, options);const instance = axios.create({baseURL: options.baseUrl ? options.baseUrl : config.baseURL,headers: options.header ? options.header : config.headers,timeout: config.timeout,withCredentials: config.withCredentials,});// request 拦截器instance.interceptors.request.use(config => {let token = Cookies.get('token');// 1. 请求开始的时候可以结合 vuex 开启全屏 loading 动画// console.log(store.state.loading)// console.log('准备发送请求...')// 2. 带上tokenif (token) {config.headers['lx-ticket'] = token;} else {// 重定向到登录页面router.push('/login')}// 3. 根据请求方法,序列化传来的参数,根据后端需求是否序列化if (config.method === 'post') {// if (config.data.__proto__ === FormData.prototype//   || config.url.endsWith('path')ton//   || config.url.endsWith('mark')//   || config.url.endsWith('patchs')// ) {// } else {// config.data = qs.stringify(config.data)// }}return config},error => {// 请求错误时console.log('request:', error)// 1. 判断请求超时if (error.code === 'ECONNABORTED' && error.message.indexOf('timeout') !== -1) {console.log('timeout请求超时')// return service.request(originalRequest);// 再重复请求一次}// 2. 需要重定向到错误页面const errorInfo = error.responseconsole.log(errorInfo)if (errorInfo) {error = errorInfo.data  // 页面那边catch的时候就能拿到详细的错误信息,看最下边的Promise.rejectconst errorStatus = errorInfo.status; // 404 403 500 ...router.push({path: `/error/${errorStatus}`})}return Promise.reject(error) // 在调用的那边可以拿到(catch)你想返回的错误信息})// response 拦截器instance.interceptors.response.use(response => {let data;// IE9时response.data是undefined,因此需要使用response.request.responseText(Stringify后的字符串)if (response.data == undefined) {data = JSON.parse(response.request.responseText)} else {data = response.data}// 根据返回的code值来做不同的处理switch (data.rc) {case 1:console.log(data.desc)break;case 0:store.commit('changeState')// console.log('登录成功')default:}// 若不是正确的返回code,且已经登录,就抛出错误// const err = new Error(data.desc)// err.data = data// err.response = response// throw errif (data && data.responseType && data.msg) {switch (data.responseType) {case "success":Message.success(data.msg);break;case "warning":Message.warning(data.msg);break;case "error":Message.error(data.msg);break;default:Message.info(data.msg);}} else {data.msg &&  Message.info(data.msg);}return data},err => {if (err && err.response) {switch (err.response.status) {case 400:err.message = '请求错误'breakcase 401:err.message = '未授权,请登录'breakcase 403:err.message = '拒绝访问'breakcase 404:err.message = `请求地址出错: ${err.response.config.url}`breakcase 408:err.message = '请求超时'breakcase 500:err.message = '服务器内部错误';if (err.config.url.includes('queryMenus.json')) {// 如果是查询菜单报错则跳转到登录页签重新登录sessionStorage.removeItem("user")Cookies.remove("token");login.logout().then((res) => {router.push('/login');}).catch(function(res) {router.push('/login');})}break;case 501:err.message = '服务未实现'breakcase 502:err.message = '网关错误'breakcase 503:err.message = '服务不可用'breakcase 504:err.message = '网关超时'breakcase 505:err.message = 'HTTP版本不受支持'breakdefault:}}console.error(err)return Promise.reject(err) // 返回接口返回的错误信息})// 请求处理instance(options).then(res => {resolve(res)return false}).catch(error => {reject(error)})})
}/*** 通用保存编辑* @param url* @param data* Form Data 形式*      name: 24*      ip: 24*      port: 24*      maxClientNum: 24*      gpuNum: 24**** stringify* qs.stringify({ a: { b: { c: 'd', e: 'f' } } });// 'a[b][c]=d&a[b][e]=f'也可以设置为  dots notationqs.stringify({ a: { b: { c: 'd', e: 'f' } } }, { allowDots: true });// 'a.b.c=d&a.b.e=f'* @returns {Promise<unknown>}*/
export const axiosCommonSave = ({url, data}) => {return new Promise((resolve, reject) => {$axios({url,data,header: formDataHeader,method: 'post',transformRequest: [function (data) {// Do whatever you want to transform the datareturn qs.stringify(data,{ allowDots: true })}],}).then((res) => {resolve(res);}).catch(err => {reject(err);})})
};/*** 通用查询* @param url* @param data* Form Data 形式pageNum: 1pageSize: 20* @returns {Promise<unknown>}*/
export const axiosCommonFindPage = ({url, data}) => {return new Promise((resolve, reject) => {$axios({url,data,method: 'post',header: formDataHeader,transformRequest: [function (data) {// Do whatever you want to transform the datareturn qs.stringify(data, {arrayFormat: 'brackets'});}],}).then((res) => {resolve(res);}).catch(err => {reject(err);})})
};/*** 通用删除* 对应后端接收参数的形式 @RequestParam("ids") String[] ids* @param url* @param data* Form data 形式* ids: 40288192722a6bb401722ae5f6520007* ids: 4028819272276694017227674fa30003* @returns {Promise<unknown>}*/
export const axiosCommonBatchDelete = ({url, data}) => {return new Promise((resolve, reject) => {$axios({url,data,method: 'post',header: formDataHeader,transformRequest: [function (data) {// Do whatever you want to transform the datareturn qs.stringify(data,{indices:false});}],}).then((res) => {resolve(res);}).catch(err => {reject(err);})})
};/*** 对应后端接收参数的形式 RequestParam("ids[]") String[] ids* @param url* @param data* Form Data形式* ids[]  40288192722a980a01722a9ee6420000* ids[]  40288192722a980a01722a9f198e0001* @returns {Promise<unknown>}*/
export const axiosBatchDeleteForArrayBrackets = ({url, data}) => {return $axios({url,method: 'post',header: formDataHeader,data,transformRequest: [function (data) {// Do whatever you want to transform the data// brackets 括号的意思return  qs.stringify(data, {arrayFormat: 'brackets'});}],})
};

uni-app + qs

近些年崛起的比较快。在使用的时候,也是需要用到数据转换的点。故贴几个实际使用的图,在了解上面用法的基础上,再次使用 qs 转换参数比较简单

安装 qs

# 使用命令安装后
npm i qs --save
import $H from '@/common/lib/request.js';
import qs from 'qs'
export default class ApiCommon {constructor(requestMapping) {this._requestMapping = requestMapping || '';this.findPage = this.findPage.bind(this);this.save = this.save.bind(this);this.batchDelete = this.batchDelete.bind(this);}findPage(data) {return $H.post(this._requestMapping + '/list.json', qs.stringify(data,{ allowDots: true }))}save(data) {return $H.post(this._requestMapping + '/save.json', qs.stringify(data,{ allowDots: true,indices:false}))}batchDelete(data) {return $H.post(this._requestMapping + '/delete.json', qs.stringify(data,{indices:false}));}
}

基础公共封装

import $store from '@/store/index.js'
import qs from 'qs'export default {// 全局配置common: {// #ifndef H5baseUrl: "http://124.70.132.32:8080",// #endif// #ifdef H5baseUrl: "",// #endifheader: {payload: {'Content-Type': 'application/json;charset=UTF-8',},formData: {'Content-Type': 'application/x-www-form-urlencoded',}},data: {},method: 'GET',dataType: 'json'},// 请求 返回promiserequest(options = {}) {// 组织参数options.url = this.common.baseUrl + options.urloptions.header = options.header || this.common.header.formDataoptions.data = options.data || this.common.dataoptions.method = options.method || this.common.methodoptions.dataType = options.dataType || this.common.dataType// tokenif (options.token) {options.header.token = $store.state.user.token// 二次验证if (options.checkToken && !options.header.token) {uni.showToast({title: '请先登录',icon: 'none'});return uni.navigateTo({url: '/pages/login/login',});}}// 请求return new Promise((res, rej) => {// 请求之前... todo// 请求中...uni.request({...options,success: (result) => {// 返回原始数据if (options.native) {return res(result)}// 服务端失败// if (result.statusCode !== 200) {//    if (options.toast !== false) {//      uni.showToast({//           title: result.data.msg || '服务端失败',//          icon: 'none'//        });//   }//     return rej(result.data)// }// 成功let data = result.datares(data)},fail: (error) => {uni.showToast({title: error.errMsg || '请求失败',icon: 'none'});return rej()}});})},// get请求get(url, data = {}, options = {}) {options.url = urloptions.data = dataoptions.method = 'GET'return this.request(options)},// post请求post(url, data = {}, options = {}) {options.url = urloptions.data = dataoptions.method = 'POST'return this.request(options)},// delete请求del(url, data = {}, options = {}) {options.url = urloptions.data = dataoptions.method = 'DELETE'return this.request(options)},postSave(url, data = {}, options = {}) {options.url = urloptions.data = qs.stringify(data, {allowDots: true,indices: false})options.method = 'POST'return this.request(options)},postFind(url, data = {}, options = {}) {options.url = urloptions.data = qs.stringify(data, {allowDots: true})options.method = 'POST'return this.request(options)},postBatchDelete(url, data = {}, options = {}) {options.url = urloptions.data = qs.stringify(data, {indices: false})options.method = 'POST'return this.request(options)}
}

qs使用方式+axios|| uni-app + qs及其基础封装相关推荐

  1. uni app 调用网络打印机_uni-app封装一个request请求

    在上一篇文章里面,写到使用uni.request请求的方法https://www.jianshu.com/p/bc62c9e1beed getList() { uni.request({url: &q ...

  2. uni app 调用网络打印机_uni-app 的使用体验总结

    [实践] uni-app 的使用总结 最近使用 uni-app 的感受. 使用体验 没用之前以为真和 Vue 一样,用了之后才知道.有点类似 Vue 和 小程序结合的感觉.写类似小程序的标签,有着小程 ...

  3. 切换 uniapp_万能前端框架uni app初探03:底部导航开发

    前言 本节我们使用uni app的底部导航功能,点击不同tab会显示不同页面,这个功能在实际项目开发中几乎是必备的. 一.基础知识 1.tabBar 如果应用是一个多 tab 应用,可以通过 tabB ...

  4. HbuilderX:uni app踩坑之uView-ui

    HbuilderX:uni app踩坑之uView-ui 最近在自学uniapp,想找一个ui框架提高一下学习和开发的效率,于是就网上冲浪,浪来浪去,最后选择了uView-ui这款.其实有些框架我是有 ...

  5. uni app 开发微信小程序及上线体验

    uni app 开发微信小程序及上线体验 项目创建及微信小程序AppId的申请 本次开发的是电商类的微信小程序,这里用到的是HBuilderX这个编辑器.之前用的Visual Studio Code ...

  6. Android uni app 列表底部白条解决方案

    uni app中android打开本地vue的列表会发现,底部有条白边. vue通过uni.getSystemInfoSync();方法获取系统信息,首次取值对,再次取值就出错 uni app每次启动 ...

  7. uni app页面传值

    传值是很常见的知识点,刚开始接触uni app总会踩到很多传值的坑,不是这里传不过去,就是那边接收不到,以下是我遇到过的一些传值方式,实在不行,咱就一个一个试,总有一个能"干起". ...

  8. uni app实现WIFI功能(只支持安卓APP)

    uni app实现WIFI功能 一.前言 二.使用 uni-WIFI 三.使用h5+ api 一.前言 最近需要在uniapp上实现WiFi功能,将个人的研究结果记录如下(都只支持安卓APP) 使用 ...

  9. uni app map 地图 漂浮问题及方案

    uni app map 地图 漂浮问题及方案 文章页有图片导致的问题,图片没加载出来,导致文章内容高度不固定,如果图片没加载出来,高度就是0,如果此时开始加载map,那么map就在那里加载,map原生 ...

最新文章

  1. STL sort()函数详解
  2. PrintWriter write与println方法的区别
  3. 【笔记】python os的使用 文件批量重命名 批量移动文件 将png转jpg代码
  4. CF-557 E. Ann and Half-Palindrome(暴力Trie)
  5. java中的配置文件
  6. C-7统计元音字母个数
  7. Is it Google Hacking? It's Google Dorking
  8. 男生们,请珍惜爱你的女人!
  9. 6.26CF模拟赛D:黑白条题题解
  10. 单片机控制步进电机-VB上位机生成S曲线
  11. 深富策略军工股掀起涨停潮
  12. 用python更换桌面壁纸
  13. 小程序实现商城案例(赋源码)
  14. Centos服务器java环境初始化搭建
  15. 关于socket长连接的心跳包
  16. 输入、输出电阻与带负载能力的总结
  17. 专访凌云光技术3D视觉业务部经理李淼:做好技术和产品,为VR行业服务
  18. Unisoc RNDIS上网业务流程学习笔记
  19. 【BZOJ4889】[Tjoi2017]不勤劳的图书管理员 分块+树状数组
  20. 用 TypeScript 写一个轻量级的 UI 框架之十三:Grid 表格组件(下)

热门文章

  1. 加速度计、陀螺仪工作原理
  2. Xilinx ISE系列教程(2):LED点灯工程、仿真、bit下载和mcs固化
  3. workbook需要引入的包_解决Maven引用POI的依赖,XSSFWorkbook依旧无法使用的问题
  4. 玩转开发板--Linux系统移植至开发板fl2440实践过程
  5. opengl开发环境搭建
  6. PAC文件解释-转载 小胡子哥的个人网站
  7. SPL 简化 SQL 案例详解:组内运算
  8. iojs 版本管理ivm
  9. 文件存储 云服务器,文件存储 云服务器
  10. 关于电脑右键缺少office三件套的解决方案