处理成树状结构,通常就是须要节点和父节点标识,或者须要考虑以哪一个节点为根节点生成树结构数据
// 使用示例代码: list: [{id: 1, pid: 0, name: 11}, {id: 2, pid: 1, name: 2}] getTreeArr({ key: 'id', pKey: 'pid', data: list }) result: [ {id: 1, pid: 0, name: 11, children: [ {id: 2, pid: 1, name: 2} ]} ]
/** * 将一级的数据结构处理成树状数据结构 * @param {Object} obj {key, pKey, data} * @param obj.key 字段名称 好比id * @param obj.pKey 父字段名称 好比 pid * @param obj.rootPValue 根节点的父字段的值 * @param obj.data 须要处理的数据 * @param obj.jsonData 是否深复制数据(默认是true) * @return {Array} arr */ getTreeArr: (obj) => { if (!Array.isArray(obj.data)) { console.log('getTreeArr=>请传入数组') return [] } obj.jsonData = obj.jsonData === false ? obj.jsonData : true const arr = obj.jsonData ? JSON.parse(JSON.stringify(obj.data)) : obj.data const 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[obj.key] !== item[obj.pKey]) { index++ } }) // 没传入根节点,根据当前数据结构获得根节点 if (!('rootPValue' in obj) && index === arr.length) { arr1.push(item) } }) // 传入根节点,根据传入的根节点组成树结构 if ('rootPValue' in obj) { arr.forEach(item => { if (item[obj.pKey] === obj.rootPValue) { arr1.push(item) } }) } return arr1 }
数组去重方法有许多,还分为普通数组和对象数组,这里列举了一些,并把其中优缺点分析了一下
/** * 数组去重 * @param {Array} data 要去重的数组 * @param {String} key 做为去重依据的字段 (处理对象数组时须要传入) * @return arr 返回处理后的数据 */
推荐使用git
handleRepeatArr ({ data, key }) { if (!Array.isArray(data)) { console.log('请传入数组') return } const arr = []; const obj = {} data.forEach((item, index) => { const attr = key ? item[key] : item if (!obj[attr]) { obj[attr] = index + 1 arr.push(item) } }) return arr }
缺点:会将数据默认排序github
handleRepeatArr ({ data, key }) { if (!Array.isArray(data)) { console.log('请传入数组') return } /** 1.递归去重,缺点,会将数据默认排序 */ // 先对数据作排序处理 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 }
缺点:适合处理数组,不适合处理对象数组element-ui
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 }
缺点:适合处理数组,不适合处理对象数组json
return [...new Set(data)]
缺点:占用内存高数组
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 }
复制成功后若是须要提示,须要自定义相关回调,当前函数使用的是element-ui的弹窗浏览器
/** * 复制 * @param {String} value 要复制的值 */ copyData (value) { const inputDom = document.createElement('input') inputDom.value = value document.body.appendChild(inputDom) inputDom.select() // 选择对象 document.execCommand('Copy') // 执行浏览器复制命令 document.body.removeChild(inputDom) // 删除DOM Message({ type: 'success', message: '复制成功' }) }
由于有些浏览器会默认拦截window.open,当须要函数中打开窗口,可使用a标签模拟window.open服务器
/** * a模拟window.open,不会被浏览器拦截 * @param {String} url a标签打开的地址 * @param {String} id a标签的ID * @param {String} targetType a标签点击打开的方式(当前页面打开仍是新窗口打开) */ openWindow: (url, targetType = '_blank', id = 'open', download = false) => { // 若是存在则删除 if (document.getElementById(id)) { document.body.removeChild(document.getElementById(id)) } const a = document.createElement('a') a.setAttribute('href', url) if (download) { a.setAttribute('download', url) } a.setAttribute('target', targetType) a.setAttribute('id', id) document.body.appendChild(a) a.click() }
这个在业务中用的比较频繁数据结构
// 使用示例代码: switchTime(new Date(), 'YYYY-MM-DD hh') // 返回 2019-05-22 11 switchTime(new Date(), 'YYYYMMDD hh:mm:ss') // 返回 20190522 11:00:00
/** * 传入时间戳,转换指定的时间格式 * @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') => { // 将字符串转换成数字 const timeStamp = +new Date(val) // 若是转换成数字出错 if (!timeStamp) { return val } let str // 获得时间字符串 const 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 }
这个方法中须要应用到上一个方法,获取当前时间,或者能够自行获得时间而后再去处理app
假设当前时间为 2019-05-20 00:00:00 // 使用示例代码: timeView(new Date()) // 刚刚发布 timeView('2019-05-19 23:01:00') // 59分钟前 timeView('2019-05-19 12:00:00') // 12小时前 timeView('2019-05-15 12:00:00') // 5天前 timeView('2019-04-15 12:00:00') // 04-15 timeView('2018-04-15 12:00:00') // 2018-04-15
/** * 时间显示 */ timeView: function (val) { const now = +new Date() // 当时时间 const timeStamp = +new Date(val) // 须要处理的时间 const result = now - timeStamp // 相差的时间戳 const min = 60 * 1000 // 分钟的毫秒数 const hour = 60 * 60 * 1000 // 小时的毫秒数 const day = 60 * 60 * 1000 * 24 // 日的毫秒数 if (result / min < 1) { return '刚刚发布' } else if (result / min < 60) { return Math.floor(result / min) + '分钟前' } else if (result / hour > 1 && result / hour < 24) { return Math.floor(result / hour) + '小时前' } else if (result / day > 1 && result / day < 7) { return Math.floor(result / day) + '天前' } else if (this.switchTime(now, 'YYYY') === this.switchTime(timeStamp, 'YYYY')) { return this.switchTime(timeStamp, 'MM月DD日') } else { return this.switchTime(timeStamp, 'YYYY年MM月DD日') } }
getLocationSearch () { const str = window.location.search const arr = str.substr(1).split('&') const obj = {} for (const item of arr) { const data = item.split('=') obj[data[0]] = data[1] } return obj }
bytesToSize (bytes) { if (bytes === 0) return '0 B' var k = 1024 // or 1024 var sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'] var i = Math.floor(Math.log(bytes) / Math.log(k)) return (bytes / Math.pow(k, i)).toPrecision(3) + ' ' + sizes[i] }
/** * 对请求失败的HTTP状态码作处理 * @param {Number} code HTTP状态码 * @param {String} message 错误提示 * @return message 返回处理过的提示信息 */ requestError: (code, message) => { const 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 } }
// 使用示例代码: list: [{key: '红色', value: 1}] getDataName({dataList: list, value: 'value', label: 'key', data: 1}) // 红色
/** * 经过key找到在列表中对应的显示 * @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 }
工具库地址函数