在闲暇之余,总结出来一部分前端常用的工具函数,后面几个操作DOM的适用于h5项目(eg:vue),其余适用于所有项目(vue、小程序等)。
/**
* 递归方式深拷贝数据
* @param {Object|Array} source 需要拷贝的对象
* @returns {Object|Array}
* 使用示例:deepClone([1,2,3,4])
*/
export function deepClone(source) {
if (!source && typeof source !== 'object') {
throw new Error('error arguments', 'deepClone')
}
const targetObj = source.constructor === Array ? [] : {}
Object.keys(source).forEach(keys => {
if (source[keys] && typeof source[keys] === 'object') {
targetObj[keys] = deepClone(source[keys])
} else {
targetObj[keys] = source[keys]
}
})
return targetObj
}
/**
* 数组根据某个字段进行排序
* @param {Array} arr 数组
* @param {String} k 字符串
* @param {Boolean} up 是否正序 默认true
* @returns {Array}
* 使用示例:sort([{a:1},{a:3},{2},{a:0}],'a',false)
*/
export function sort(arr, k, up = true) {
if (!Array.isArray(arr)) {
throw new Error('数据类型必须是数组');
}
return arr.sort(compare(k, up));
}
/**
* 为了满足数组根据某个字段进行排序
* @param {*} k 数组关键词
* @param {*} up 是否是正序 默认true
*/
export function compare(k, up = true) {
return function(a, b) {
var v1 = a[k];
var v2 = b[k];
return up ? v1 - v2 : v2 - v1;
}
}
/**
* 根据对象用&拼接返回
* @param {Object} json 对象
* @returns {String}
* 使用示例:param({a:1,b:2}) 返回:a=1&b=2
*/
export function param(json) {
if (!json) return ''
let newjson = Object.keys(json).map(key => {
if (json[key] === undefined) return ''
return encodeURIComponent(key) + '=' + encodeURIComponent(json[key])
})
return newjson.join('&');
}
/**
* 根据时间戳+随机数生成32进制的字符串
* @returns {string}
* 使用示例:createUniqueString()
*/
export function createUniqueString() {
const timestamp = +new Date() + ''
const randomNum = parseInt((1 + Math.random()) * 65536) + ''
return (+(randomNum + timestamp)).toString(32)
}
/**
* 根据地址栏返回参数对象
* @param {string} url 地址 非必传
* @returns {Object}
* getQueryObject('http://localhost:8080/demo#/demo?id=1&ff=2233'); 返回:{id: '1', ff: '2233'}
*/
export function getQueryObject(url) {
url = url == null ? window.location.href : url
const search = url.substring(url.lastIndexOf('?') + 1)
const obj = {}
const reg = /([^?&=]+)=([^?&=]*)/g
search.replace(reg, (rs, $1, $2) => {
const name = decodeURIComponent($1)
let val = decodeURIComponent($2)
val = String(val)
obj[name] = val
return rs
})
return obj
}
/**
* 防抖
* @param {Function} fn 回调函数
* @param {number} dealy 等待时间
* */
export function debounce(fn, dealy) {
let timer = null;
return function() {
if (timer) {
clearTimeout(timer)
}
timer = setTimeout(fn, dealy)
}
}
/**
* 节流
* @param {Function} fn 回调函数
* @param {number} dealy 等待时间
* */
export function throttle(fn, dealy) {
let flag = true;
return function() {
if (!flag) {
return false;
}
flag = false;
setTimeout(() => {
fn();
flag = true;
}, dealy)
}
}
/**
* 数组去重
* @param {Object} array 数组
* @returns {Array}
* 使用示例:removeRepeat([1,2,3,4,1,1]);返回[1,2,3,4]
*/
export function removeRepeat(array) {
return Array.from(new Set(array));
}
/**
* 字符串去掉转移符号
* @param {Object} str
* @returns {String}
* 使用示例:removeSymbol('gdhjk\b')
*/
export function removeSymbol(str) {
return str.replace(/[\'\"\\\/\b\f\n\r\t]/g, '');
}
/**
* Merges two objects, giving the last one precedence
* @param {Object} target
* @param {(Object|Array)} source
* @returns {Object}
* 使用示例:objectMerge({a:1},{b:2});返回:{a:1,b:2}
*/
export function objectMerge(target, source) {
if (typeof target !== 'object') {
target = {}
}
if (Array.isArray(source)) {
return source.slice()
}
Object.keys(source).forEach(property => {
const sourceProperty = source[property]
if (typeof sourceProperty === 'object') {
target[property] = objectMerge(target[property], sourceProperty)
} else {
target[property] = sourceProperty
}
})
return target
}
// =============时间相关=================
/**
* Parse the time to string 处理时间 自定义返回形式
* @param {(Object|string|number)} time
* @param {string} cFormat
* @returns {string | null}
* 使用示例:parseTime(new Date(),'{y}-{m}-{d} {h}:{i}:{s} 今天是星期{a}'); 返回:2021-10-15 17:52:38 今天是星期五
*/
export function parseTime(time, cFormat) {
if (arguments.length === 0 || !time) {
return null
}
const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}'
let date
if (typeof time === 'object') {
date = time
} else {
if ((typeof time === 'string')) {
if ((/^[0-9]+$/.test(time))) {
// support "1548221490638"
time = parseInt(time)
} else {
// support safari
// https://stackoverflow.com/questions/4310953/invalid-date-in-safari
time = time.replace(new RegExp(/-/gm), '/')
}
}
if ((typeof time === 'number') && (time.toString().length === 10)) {
time = time * 1000
}
date = new Date(time)
}
const formatObj = {
y: date.getFullYear(),
m: date.getMonth() + 1,
d: date.getDate(),
h: date.getHours(),
i: date.getMinutes(),
s: date.getSeconds(),
a: date.getDay()
}
const time_str = format.replace(/{([ymdhisa])+}/g, (result, key) => {
const value = formatObj[key]
// Note: getDay() returns 0 on Sunday
if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value ] }
return value.toString().padStart(2, '0')
})
return time_str
}
/**
* 获取当天时间段
* @returns {Array}
* 使用示例:getCurrentDay();返回:["2020-05-20 00:00:00", "2020-5-20 23:59:59"]
*/
export function getCurrentDay() {
var date = new Date();
let year = date.getFullYear();
let month = ((date.getMonth() + 1) < 10 ? "0" + (date.getMonth() + 1) : (date.getMonth() + 1));
let day = (date.getDate() < 10 ? "0" + date.getDate() : date.getDate());
var startTime = year + "-" + month + "-" + day + " " + "00:00:00";
var endTime = year + '-' + month + '-' + day + ' ' + date.getHours() + ':' + date.getMinutes() + ':' + date.getSeconds();
return [startTime, endTime]
}
/**
* 获取时间段相隔的小时数
* @param {string} time1 第1个时间
* @param {string} time2 第2个时间
* @returns {Number}
*/
export function timeRangeHour(time1, time2) {
let usedTime = new Date(time2).getTime() - new Date(time1).getTime();
return (Math.ceil((usedTime / 1000) / 60) / 60);
}
/**
* 倒计时
* @param {Object} time 秒
* @param {Object} fn 回调函数
* @returns {Number}
* 使用示例:countdown(60,(s)=>{console.log(s)}); 返回秒
*/
export function countdown(time = 10, fn) {
let _t = time,
_timer = null;
if (fn) fn(_t);
_timer = setInterval(() => {
_t--;
if (fn) fn(_t);
if (_t <= 0) {
clearInterval(_timer);
}
}, 1000)
}
// =============元素处理,适用于直接操作DOM=================
/**
* Check if an element has a class
* @param {HTMLElement} ele 元素
* @param {string} cls 类名
* @returns {boolean}
* 使用示例:hasClass(document.querySelector('.dd'),'dd2')
*/
export function hasClass(ele, cls) {
return !!ele.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)'))
}
/**
* Add class to element
* @param {HTMLElement} elm
* @param {string} cls
* 使用示例:hasClass(document.querySelector('.dd'),'dd3')
*/
export function addClass(ele, cls) {
if (!hasClass(ele, cls)) ele.className += ' ' + cls
}
/**
* Remove class from element
* @param {HTMLElement} elm
* @param {string} cls
* 使用示例:hasClass(document.querySelector('.dd'),'dd')
*/
export function removeClass(ele, cls) {
if (hasClass(ele, cls)) {
const reg = new RegExp('(\\s|^)' + cls + '(\\s|$)')
ele.className = ele.className.replace(reg, ' ')
}
}
后面有更实用的,会持续更新~