utils.js
/**
* 判断是否是对象
* @param {*} value
* @returns {boolean}
*/
export const isObject = (obj) => obj !== null && typeof obj === 'object'
/**
* 判断是否是数组
* @param {*} value
* @returns {boolean}
* @example
* isArray([]) // true
*/
export const isArray = Array.isArray
/**
* 判断是否是函数
* @param {*} value
* @returns {boolean}
* @example
*/
export const isFunction = (value) => typeof value === 'function'
/**
* 判断是否是字符串
* @param {*} value
* @returns {boolean}
* @example
* isString('') // true
*/
export const isString = (value) => typeof value === 'string'
/**
* 判断是否是数字
* @param {*} value
* @returns {boolean}
* @example
* isNumber(1) // true
* isNumber('1') // false
*/
export const isNumber = (value) => typeof value === 'number'
/**
* 判断是否是布尔值
* @param {*} value
* @returns {boolean}
* @example
* isBoolean(true) // true
*/
export const isBoolean = (value) => typeof value === 'boolean'
/**
* 判断是否是undefined
* @param {*} value
* @returns {boolean}
* @example
* isUndefined(undefined) // true
*/
export const isUndefined = (value) => typeof value === 'undefined'
/**
* 判断是否是空对象
* @param {*} value
* @returns {boolean}
* @example
* isEmptyObject({}) // true
*/
export const isEmptyObject = (obj) => {
if (!isObject(obj)) return false
for (let key in obj) {
return false
}
return true
}
/**
* 去除字符串两端空格
* @param {string} str
* @returns {string}
* @example
* trim(' 123 ') // '123'
*/
export const trim = (str) => str.replace(/^\s+|\s+$/g, '')
/**
* 去除所有空格
* @param {string} str
* @returns {string}
* @example
* trimAll(' 123 ') // '123'
*/
export const trimAll = (str) => str.replace(/\s+/g, '')
/**
* 替换相同字符串
* @param {string} str
* @param {string} search
* @param {string} replace
* @returns {string}
* @example
* replaceAll('123123', '1', '2') // '223223'
*/
export const replaceAll = (str, search, replace) => str.replace(new RegExp(search, 'g'), replace)
/**
* 金额格式化
* @param {number} num
* @param {number} n
* @returns {string}
* @example
* formatMoney(123456789, 2) // '123,456,789.00'
*/
export const formatMoney = (num, n = 2) => {
if (!isNumber(num)) return num
num = num.toFixed(n)
let re = /(-?\d+)(\d{3})/
while (re.test(num)) {
num = num.replace(re, '$1,$2')
}
return num
}
/**
* 金额反格式化
* @param {string} str
* @returns {number}
* @example
* unFormatMoney('123,456,789.00') // 123456789
*/
export const unFormatMoney = (str) => {
if (!isString(str)) return str
return parseFloat(str.replace(/[^\d\.-]/g, ''))
}
/**
* 格式化手机号码
* @param {string} str
* @returns {string}
* @example
* formatPhone('12345678901') // '123 4567 8901'
*/
export const formatPhone = (str) => {
if (!isString(str)) return str
return str.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2')
}
/**
* 生成随机数
* @param {number} min
* @param {number} max
* @returns {number}
* @example
* random(1, 10) // 5
*/
export const random = (min, max) => Math.floor(Math.random() * (max - min + 1) + min)
/**
* 生成随机字符串
* @param {number} len
* @returns {string}
* @example
*/
export const randomString = (len = 32) => {
let chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
let maxPos = chars.length
let str = ''
for (let i = 0; i < len; i++) {
str += chars.charAt(Math.floor(Math.random() * maxPos))
}
return str
}
/**
* 手机号码验证
* @param {String} phone 手机号码
* @returns {Boolean} true:合法 false:不合法
* @example
* isPhone('12345678901') // true
*/
export function isPhone(phone) {
return /^1[3456789]\d{9}$/.test(phone)
}
/**
* 邮箱验证
* @param {String} email 邮箱
* @returns {Boolean} true:合法 false:不合法
* @example
* isEmail('
*/
export function isEmail(email) {
return /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(.[a-zA-Z0-9_-])/.test(email)
}
/**
* 身份证号码验证
* @param {String} idCard 身份证号码
* @returns {Boolean} true:合法 false:不合法
* @example
* isIdCard('123456789012345678') // true
*/
export function isIdCard(idCard) {
return /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/.test(idCard)
}
/**
* 银行卡号验证
* @param {String} bankCard 银行卡号
* @returns {Boolean} true:合法 false:不合法
* @example
* isBankCard('123456789012345678') // true
*/
export function isBankCard(bankCard) {
return /^([1-9]{1})(\d{14}|\d{18})$/.test(bankCard)
}
/**
* 验证码验证
* @param {String} code 验证码
* @returns {Boolean} true:合法 false:不合法
* @example
* isCode('123456') // true
*/
export function isCode(code) {
return /^\d{6}$/.test(code)
}
/**
* 密码验证
* @param {String} password 密码
* @returns {Boolean} true:合法 false:不合法
* @example
* isPassword('123456') // true
*/
export function isPassword(password) {
return /^[a-zA-Z0-9]{6,16}$/.test(password)
}
/**
* 数组去重
* @param {Array} arr 数组
* @returns {Array} 去重后的数组
* @example
* unique([1, 2, 3, 4, 5, 1, 2, 3, 4, 5]) // [1, 2, 3, 4, 5]
*/
export function unique(arr) {
return Array.from(new Set(arr))
}
/**
* 数组乱序
* @param {Array} arr 数组
* @returns {Array} 乱序后的数组
* @example
* shuffle([1, 2, 3, 4, 5]) // [2, 4, 1, 5, 3]
*/
export function shuffle(arr) {
return arr.sort(() => Math.random() - 0.5)
}
/**
* json去重
* @param {Array} arr 数组
* @param {String} key 去重的key
* @returns {Array} 去重后的数组
* @example
* uniqueJson([{id: 1}, {id: 2}, {id: 1}], 'id') // [{id: 1}, {id: 2}]
*/
export function uniqueJson(arr, key) {
return Array.from(new Set(arr.map(item => item[key]))).map(id => {
return arr.find(item => item[key] === id)
})
}
/**
* 数组转树形结构
* @param {Array} arr 数组
* @param {String} id id
* @param {String} pid 父id
* @param {String} children 子集
* @returns {Array} 树形结构
* @example
* arrayToTree([{id: 1, pid: 0}, {id: 2, pid: 1}, {id: 3, pid: 2}], 'id', 'pid', 'children')
*/
export function arrayToTree(arr, id, pid, children) {
const data = JSON.parse(JSON.stringify(arr))
const result = []
if (!id || !pid || !children) {
return result
}
if (Array.isArray(data)) {
data.forEach(item => {
delete item.children
})
const map = {}
data.forEach(item => {
map[item[id]] = item
})
data.forEach(item => {
const parent = map[item[pid]]
if (parent) {
(parent[children] || (parent[children] = [])).push(item)
} else {
result.push(item)
}
})
}
return result
}
/**
* 防抖
* @param {Function} fn 函数
* @param {Number} delay 延迟时间
* @returns {Function} 防抖函数
* @example
* debounce(() => console.log('防抖'), 1000)
* */
export function debounce(fn, delay) {
let timer = null
return function () {
if (timer) {
clearTimeout(timer)
}
timer = setTimeout(() => {
fn.apply(this, arguments)
}, delay)
}
}
/**
* 节流
* @param {Function} fn 函数
* @param {Number} delay 延迟时间
* @returns {Function} 节流函数
* @example
* throttle(() => console.log('节流'), 1000)
* */
export function throttle(fn, delay) {
let timer = null
return function () {
if (!timer) {
timer = setTimeout(() => {
fn.apply(this, arguments)
timer = null
}, delay)
}
}
}
/*********************** 对象操作 ***********************/
/**
* 深拷贝
* @param {Object} obj 对象
* @returns {Object} 深拷贝后的对象
* @example
* deepClone({a: 1, b: {c: 2}}) // {a: 1, b: {c: 2}}
*/
export function deepClone(obj) {
return JSON.parse(JSON.stringify(obj))
}
/**
* 对象转数组
* @param {Object} obj 对象
* @returns {Array} 数组
* @example
* objectToArray({a: 1, b: 2}) // [{key: 'a', value: 1}, {key: 'b', value: 2}]
* */
export function objectToArray(obj) {
return Object.keys(obj).map(key => ({
key,
value: obj[key]
}))
}
/**
* 链式读取对象属性
* @param {Object} obj 对象
* @param {String} path 属性路径
* @returns {Object} 属性值
* @example
* getPropByPath({a: {b: {c: 1}}}, 'a.b.c') // 1
* */
export function getPropByPath(obj, path) {
const paths = path.split('.')
let current = obj
for (let i = 0; i < paths.length; i++) {
if (!current) break
current = current[paths[i]]
}
return current
}
/**
* 深度合并对象
* @param {Object} target 目标对象
* @param {Object} source 源对象
* @returns {Object} 合并后的对象
* @example
* deepMerge({a: 1, b: {c: 2}}, {b: {d: 3}}) // {a: 1, b: {c: 2, d: 3}}
* */
export function deepMerge(target, source) {
for (const key in source) {
if (source.hasOwnProperty(key)) {
if (source[key] && source[key].constructor === Object) {
target[key] = target[key] || {}
deepMerge(target[key], source[key])
} else {
target[key] = source[key]
}
}
}
return target
}