在开发项目的时候,有一些场景用到次数频繁的函数,就封装在了自己的工具类里,在这里和大家分享一下
1. 通过value获取到数据列表中对应显示的字段
经常做平台类的项目,容易碰到这样的场景,增删改查页面,添加完之后,表格要显示某个类型,但是接口返回数据是类型ID,就可以通过这个方法得到对应要显示的字段了。
用法示例:let list = [{id: 1, name: '深圳'}, {id: 2, name: '广州'}]
getDataName({dataList: arr, value: 'id', label: 'name', data: 1}) // 深圳
getDataName({dataList: arr, value: 'id', label: 'name', data: 2}) // 广州
/**
* 通过value找到在列表中对应的名字
* @param {Object} obj
* @param obj.dataList 数据列表
* @param obj.value 数据的值对应的字段名称 例如 'value'
* @param obj.label 数据的说明对应的字段名称 例如 'label'
* @param obj.data 当前传入的数据值
* @return name 返回当前传入值在数组中对应的名字
*/
getDataName: (obj) => {
let name = obj.data
if (Array.isArray(obj.dataList) && obj.dataList.length > 0) {
for (let i = 0; i < obj.dataList.length; i++) {
if (obj.dataList[i][obj.value] == obj.data) {
name = obj.dataList[i][obj.label]
}
}
}
return name
}
2. 对请求失败的HTTP状态码做处理
说多了都是泪,之前公司接口返回数据,一开始没有做异常处理,然后在使用的时候一旦出现什么问题页面上就是一大堆的英文,很长很长一串,或者是出现问题了不返回错误原因,然后说影响用户体验,但是后端又不做异常处理,于是就写了一个关于http状态码的处理。根据返回的状态码页面上显示对应的提示内容,不过感觉稍微正常的流程都用不上这个,哈哈
/**
* 对请求失败的HTTP状态吗做处理
* @param {Number} code HTTP状态码
* @param {String} message 错误提示
* @return message 返回处理过的提示信息
*/
requestError: (code, message) => {
let statusCode = (code + '').replace(/[^0-9]+/g, '') - 0
switch (statusCode) {
case 400:
return 'Bad Request (错误的请求)'
case 401:
return 'Unauthorized (请求要求身份验证)'
case 403:
return 'Forbidden (服务器拒绝请求)'
case 404:
return 'NOT Found (服务器找不到请求的资源)'
case 405:
return 'Bad Request (禁用请求中指定的方法)'
case 406:
return 'Not Acceptable (无法使用请求的内容特性响应请求的网页)'
case 407:
return 'Proxy Authentication Required (需要代理授权)'
case 408:
return 'Request Timed-Out (服务器等候请求时发生超时)'
case 409:
return 'Conflict (服务器在完成请求时发生冲突。服务器必须在响应中包含有关冲突的信息)'
case 410:
return 'Gone (请求的资源已被永久删除)'
case 411:
return 'Length Required (服务器不接受不含有效内容长度标头字段的请求)'
case 412:
return 'Precondition Failed (未满足前提条件)'
case 413:
return 'Request Entity Too Large (请求实体过大)'
case 414:
return 'Request, URI Too Large (请求的 URI 过长)'
case 415:
return 'Unsupported Media Type (不支持的媒体类型)'
case 429:
return '您的操作过于频繁,请稍后重试'
case 500:
return 'Internal Server Error (服务器内部错误)'
case 501:
return 'Not Implemented (尚未实施)'
case 502:
return 'Bad Gateway (错误网关)'
case 503:
return 'Server Unavailable (服务不可用)'
case 504:
return 'Gateway Timed-Out (网关超时)'
case 505:
return 'HTTP Version not supported (HTTP 版本不受支持)'
default:
return message
}
},
3. 传入时间戳,转换指定的时间格式
这个是本人用的非常多的一个函数,平时经常需要对时间处理,就只需要传入时间戳或者时间格式的字符串,然后指定要转换的时间格式,就可以了,很方便
用法示例:switchTime(new Date()) // 传入当前时间,默认返回当时时间,格式为 YYYY-MM-DD hh:mm:ss
switchTime('2018-11-10', 'YYYY.MM.DD') // 2018.11.10
/**
* 传入时间戳(或者时间格式的数据),转换指定的时间格式
* @param {Number} val 时间戳(或者时间格式的数据)
* @param {String} dateType 要得到的时间格式 例如 YYYY-MM-DD hh:mm:ss
* @return dataStr 例如 YYYY-MM-DD hh:mm:ss
*/
switchTime: (val = +new Date(), dateType = 'YYYY-MM-DD hh:mm:ss') => {
// 将字符串转换成数字
let timeStamp, dateStr, str
timeStamp = +new Date(val)
// 如果转换成数字出错
if (!timeStamp) {
return val
}
// 得到时间字符串
dateStr = new Date(timeStamp)
str = dateType.replace('YYYY', dateStr.getFullYear())
str = str.replace('MM', (dateStr.getMonth() + 1 < 10 ? '0' : '') + (dateStr.getMonth() + 1))
str = str.replace('DD', (dateStr.getDate() < 10 ? '0' : '') + dateStr.getDate())
str = str.replace('hh', (dateStr.getHours() < 10 ? '0' : '') + dateStr.getHours())
str = str.replace('mm', (dateStr.getMinutes() < 10 ? '0' : '') + dateStr.getMinutes())
str = str.replace('ss', (dateStr.getSeconds() < 10 ? '0' : '') + dateStr.getSeconds())
return str
}
4. 浏览器打开新窗口
在平时开发中,一定会有这样的需求,打开新窗口。但是用window.open的方式往往会碰到被浏览器拦截的问题,所以可以用a标签通过超链接的方式打开新窗口。
往往在下载文件的时候也会用到这个方法。不过下载文件分为几种情况,一种是直接访问一个地址,浏览器会自动解析并且下载,还有一种情况就是后端返回的是一个文件,这个时候需要先在响应类型中加上blob处理之后,再去处理。这种情况下访问解析后的地址,往往是打开一个新窗口并访问,并不会自动下载,而需要下载的话需要给a标签再加上一个download属性。
用法示例:openWindow('https://www.baidu.com') // 默认打开方式为新窗口, id为open
/**
* a模拟window.open,不会被浏览器拦截
* @param {String} url a标签打开的地址
* @param {String} id a标签的ID
* @param {String} targetType a标签点击打开的方式(当前页面打开还是新窗口打开)
*/
openWindow: (url, targetType = '_blank', id = 'open') => {
// 如果存在则删除
if (document.getElementById(id)) {
document.body.removeChild(document.getElementById(id))
}
let a = document.createElement('a')
a.setAttribute('href', url)
a.setAttribute('download', url)
a.setAttribute('target', targetType)
a.setAttribute('id', id)
document.body.appendChild(a)
a.click()
},
5. 将有层级关系的列表转换成树状数据
不知道大家碰到树状结构的情况,但是本人开发的时候,因为开发的平台类的项目较多,所以经常碰到树状的数据结构。
以前都是叫后端直接返回树状数据的,但是后端好像也不喜欢处理这样的数据,就自己写了一个方法。
传入有层级关系的列表数据,然后根据定义的参数,处理成树状的数据结构。
用法示例:let arr = [{id: 1, pid: 0, name: '一级'}, {id: 2, pid: 1, name: '二级'}],
arr1 = getTreeArr({key: 'id', pKey: 'pid', rootPValue: 0, data: arr})
得到的数据为:
arr1 = [
{id: 1, pid: 0, name: '一级', children: [{id: 2, pid: 1, name: '二级', children: []}]
}
]
/**
* 将一级的数据结构处理成树状数据结构
* @param {Object} obj {key, pKey, data}
* @param obj.key 字段名称 比如id
* @param obj.pKey 父字段名称 比如 pid
* @param obj.rootPValue 根节点的父字段的值
* @param obj.data 需要处理的数据
* @return {Array} arr
*/
getTreeArr: (obj) => {
if (!Array.isArray(obj.data)) {
console.log('getTreeArr=>请传入数组')
return []
}
let arr = obj.data, arr1 = []
// 将数据处理成数状结构
arr.forEach(item => {
let index = 0
item.children = []
arr.forEach(item1 => {
// 得到树结构关系
if (item[obj.key] === item1[obj.pKey]) {
item.children.push(item1)
}
// 判断根节点
if (item1.id !== item.pid) {
index++
}
// 传入根节点,根据传入的根节点组成树结构
if (rootPValue in obj && item[obj.pKey] === obj.rootPValue) {
arr1.push(item)
}
})
// 没传入根节点,根据当前数据结构得到根节点
if (!(rootPValue in obj) && index === arr.length) {
arr1.push(item)
}
})
return arr1
}
6. 占位显示
写vue组件的时候,总是习惯用对象去做参数,因为觉得把参数变成对象的形式维护起来会非常方便,每次增加参数的时候只需要在对象中加上属性,接受的地方对属性做处理就好了。
但是vue组件的话,Object是不能设置默认值的,没有默认值的话,读取对象的属性便是一个错误的语法,所以就写了一个占位显示的方法,比如
用法示例:showData(obj, 'name', '名字') // 当obj未传入的时候显示 ‘名字’, 传入后显示为 obj.name
/**
* 用来判断对象不存在是,显示的字段数据
* @param {Object} obj 对象
* @param {String} key 要显示的属性
* @param {String} staticName 属性不存在时显示的值
*/
showData (obj, key, staticName) {
if (!obj) {
obj = {}
}
if (obj && obj[key]) {
return obj[key]
} else {
return staticName
}
}
7. 数组(对象数组去重)
- 使用和参数说明
用法示例:handleRepeatArr({data: [1 , 1 ,1]}) // [1]
handleRepeatArr({data: [{name: 1}, {name: 1}], key: 'name'}) // [{name: 1}]
/**
- 数组去重
- @param {Array} data 要去重的数组
- @param {String} key 作为去重依据的字段 (处理对象数组时需要传入)
- @return arr 返回处理后的数据
*/
- 1.递归去重(数据无法保持之前的排序)
handleRepeatArr ({data, key}) {
if (!Array.isArray(data)) {
console.log('请传入数组')
return
}
// 先对数据做排序处理
data = data.sort((item, item1) => {
if (key) {
return item[key] - item1[key]
}
return item - item1
})
// 递归去重
function getData (index) {
if (index >= 1) {
// 判断当前数据和下一条数据是否相等
let result = key ? data[index][key] === data[index - 1][key] : data[index] === data[index - 1]
if (result) {
data.splice(index, 1)
}
getData(index - 1)
}
}
getData(data.length - 1)
return data
}
- 2.根据对象的属性不同去重 (推荐使用)
handleRepeatArr ({data, key}) {
if (!Array.isArray(data)) {
console.log('请传入数组')
return
}
let arr = [], obj = {}
data.forEach((item, index) => {
let attr = key ? item[key] : item
if (!obj[attr]) {
obj[attr] = index + 1
arr.push(item)
}
})
return arr
}
- 3.利用indexOf以及forEach (适合处理数组,不适合处理对象数组)
handleRepeatArr ({data, key}) {
if (!Array.isArray(data)) {
console.log('请传入数组')
return
}
let arr = []
data.forEach((item, index) => {
// 如果当前元素在之后没有出现过(后面出现的数据会保留)
// let result = data.indexOf(item, index + 1)
// 如果当前元素在之前没有出现过(前面出现的数据会保留)
let result = index === 0 ? -1 : data.lastIndexOf(item, index - 1)
if (result === -1) {
arr.push(item)
}
})
return arr
}
- 4.双层循环去重 (占用内存高)
handleRepeatArr ({data, key}) {
if (!Array.isArray(data)) {
console.log('请传入数组')
return
}
for (let i = 0, len = data.length; i < len; i++) {
for (let j = i + 1; j < len; j++) {
let result = key ? data[i][key] === data[j][key] : data[i] === data[j]
if (result) {
data.splice(j, 1)
len--
j--
}
}
}
return data
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。