当前位置: 首页 > news >正文

常用工具函数推荐:前端开发常用的工具函数(拷贝、排序、防抖、去重、合并、时间处理、DOM操作...).md

在闲暇之余,总结出来一部分前端常用的工具函数,后面几个操作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, ' ')
  }
}

后面有更实用的,会持续更新~

相关文章:

  • 正则表达式校验文件路径
  • img制图技巧:给img图片添加背景颜色和背景图片,制作出新图片
  • 移动端h5页面click事件延迟300ms,出现该问题的原因分析及解决方案FastClick.js
  • ios移动端兼容:iPhone X等机型底部的安全距离样式的设置
  • js简单判断:js判断对象是否为{},js判断对象是否为null
  • Linux Pmap 命令:查看进程用了多少内存
  • HBuilder X运行uniapp之app真机调试控制台console不打印,多种原因分析解决,亲测有效
  • 开源项目推荐:推荐5款前端的开源项目,vue、uniapp、react学无止境用无止境_
  • uniapp插件开发:uniapp之slider滑动选择插件,方向支持横向和竖向,更多参数可配置化
  • 与 ConTeXt MkIV 官方文档的接驳
  • uniapp插件开发:uniapp使用uni_modules开发插件、发布插件,直接导入,一键升级
  • 小程序跳转:小程序之间的跳转详细步骤(公众号绑定小程序、wx.navigateToMiniProgram实现跳转)
  • JAVA调用DLL使用JNA详细说明实例
  • 小程序跳转:云开发之h5跳小程序
  • 使用系统的CoreLocation定位
  • 230. Kth Smallest Element in a BST
  • canvas实际项目操作,包含:线条,圆形,扇形,图片绘制,图片圆角遮罩,矩形,弧形文字...
  • JAVA SE 6 GC调优笔记
  • Linux链接文件
  • Netty+SpringBoot+FastDFS+Html5实现聊天App(六)
  • node.js
  • node-glob通配符
  • Python学习之路16-使用API
  • Rancher-k8s加速安装文档
  • Traffic-Sign Detection and Classification in the Wild 论文笔记
  • vue+element后台管理系统,从后端获取路由表,并正常渲染
  • 复习Javascript专题(四):js中的深浅拷贝
  • 官方解决所有 npm 全局安装权限问题
  • 盘点那些不知名却常用的 Git 操作
  • 如何使用 JavaScript 解析 URL
  • 数据库写操作弃用“SELECT ... FOR UPDATE”解决方案
  • 通过npm或yarn自动生成vue组件
  • 推荐一款sublime text 3 支持JSX和es201x 代码格式化的插件
  • 想使用 MongoDB ,你应该了解这8个方面!
  • 一道闭包题引发的思考
  • 一份游戏开发学习路线
  • 用jQuery怎么做到前后端分离
  • LevelDB 入门 —— 全面了解 LevelDB 的功能特性
  • 你学不懂C语言,是因为不懂编写C程序的7个步骤 ...
  • 说说我为什么看好Spring Cloud Alibaba
  • ​ ​Redis(五)主从复制:主从模式介绍、配置、拓扑(一主一从结构、一主多从结构、树形主从结构)、原理(复制过程、​​​​​​​数据同步psync)、总结
  • #Z0458. 树的中心2
  • (windows2012共享文件夹和防火墙设置
  • (八)光盘的挂载与解挂、挂载CentOS镜像、rpm安装软件详细学习笔记
  • (二)Eureka服务搭建,服务注册,服务发现
  • (仿QQ聊天消息列表加载)wp7 listbox 列表项逐一加载的一种实现方式,以及加入渐显动画...
  • (论文阅读32/100)Flowing convnets for human pose estimation in videos
  • (十八)SpringBoot之发送QQ邮件
  • (算法)求1到1亿间的质数或素数
  • (一)Linux+Windows下安装ffmpeg
  • (原创)攻击方式学习之(4) - 拒绝服务(DOS/DDOS/DRDOS)
  • (转)创业家杂志:UCWEB天使第一步
  • .naturalWidth 和naturalHeight属性,
  • .NET / MSBuild 扩展编译时什么时候用 BeforeTargets / AfterTargets 什么时候用 DependsOnTargets?
  • .NET C#版本和.NET版本以及VS版本的对应关系