前言 随着开发经验的积累,很多人会有自己的常用站点,一些网址收藏,自己造的轮子或者别人的轮子,工具函数库等等。 这里提供一些常用的工具函数,如果你也有一些觉得挺不错的库,欢迎在下方评论💓。
格式化时间戳 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 export function formatDateTimeStamp (date, fmt ) { if (/(y+)/ .test (fmt)) { fmt = fmt.replace (RegExp .$1 , (date.getFullYear () + '' ).substr (4 - RegExp .$1 .length )) } let o = { 'M+' : date.getMonth () + 1 , 'd+' : date.getDate (), 'h+' : date.getHours (), 'm+' : date.getMinutes (), 's+' : date.getSeconds () } for (let k in o) { if (new RegExp (`(${k} )` ).test (fmt)) { let str = o[k] + '' fmt = fmt.replace ( RegExp .$1 , (RegExp .$1 .length === 1 ) ? str : padLeftZero (str)) } } return fmt } function padLeftZero (str ) { return ('00' + str).substr (str.length ); } export function parseTime (time, cFormat ) { if (arguments .length === 0 ) { return null } const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}' let date if (typeof time === 'object' ) { date = time } else { if ((typeof time === 'string' ) && (/^[0-9]+$/ .test (time))) { time = parseInt (time) } 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] if (key === 'a' ) { return ['日' , '一' , '二' , '三' , '四' , '五' , '六' ][value] } return value.toString ().padStart (2 , '0' ) }) return time_str }
时间格式化 几分钟前 几小时前 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 export function formatTime (time, option ) { if (('' + time).length === 10 ) { time = parseInt (time) * 1000 } else { time = +time } const d = new Date (time) const now = Date .now () const diff = (now - d) / 1000 if (diff < 30 ) { return '刚刚' } else if (diff < 3600 ) { return Math .ceil (diff / 60 ) + '分钟前' } else if (diff < 3600 * 24 ) { return Math .ceil (diff / 3600 ) + '小时前' } else if (diff < 3600 * 24 * 2 ) { return '1天前' } if (option) { return parseTime (time, option) } else { return ( d.getMonth () + 1 + '月' + d.getDate () + '日' + d.getHours () + '时' + d.getMinutes () + '分' ) } } function pluralize (time, label ) { if (time === 1 ) { return time + label + ' ago' } return time + label + 's' + ' ago' } export function timeAgo (time ) { const between = Date .now () / 1000 - Number (time) if (between < 3600 ) { return pluralize (~~(between / 60 ), ' minute' ) } else if (between < 86400 ) { return pluralize (~~(between / 3600 ), ' hour' ) } else { return pluralize (~~(between / 86400 ), ' day' ) } }
url参数转为对象 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 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 } export function param2Obj (url ) { const search = url.split ('?' )[1 ] if (!search) { return {} } return JSON .parse ( '{"' + decodeURIComponent (search) .replace (/"/g , '\\"' ) .replace (/&/g , '","' ) .replace (/=/g , '":"' ) .replace (/\+/g , ' ' ) + '"}' ) }
对象序列化【对象转url参数】 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 function cleanArray (actual ) { const newArray = [] for (let i = 0 ; i < actual.length ; i++) { if (actual[i]) { newArray.push (actual[i]) } } return newArray } export function param (obj ) { if (!obj) return '' return cleanArray ( Object .keys (obj).map (key => { if (obj[key] === undefined ) return '' return encodeURIComponent (key) + '=' + encodeURIComponent (obj[key]) }) ).join ('&' ) } export function stringfyQueryStr (obj ) { if (!obj) return '' ; let pairs = []; for (let key in obj) { let value = obj[key]; if (value instanceof Array ) { for (let i = 0 ; i < value.length ; ++i) { pairs.push (encodeURIComponent (key + '[' + i + ']' ) + '=' + encodeURIComponent (value[i])); } continue ; } pairs.push (encodeURIComponent (key) + '=' + encodeURIComponent (obj[key])); } return pairs.join ('&' ); } param ({name :'1111' ,sex :'wwww' })stringfyQueryStr ({name :'1111' ,sex :'wwww' })
本地存储 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 export const store = { set : function (name, value, day ) { let d = new Date () let time = 0 day = (typeof (day) === 'undefined' || !day) ? 1 : day time = d.setHours (d.getHours () + (24 * day)) localStorage .setItem (name, JSON .stringify ({ data : value, time : time })) }, get : function (name ) { let data = localStorage .getItem (name) if (!data) { return null } let obj = JSON .parse (data) if (new Date ().getTime () > obj.time ) { localStorage .removeItem (name) return null } else { return obj.data } }, clear : function (name ) { if (name) { localStorage .removeItem (name) } else { localStorage .clear () } } }
cookie操作 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 export const cookie = { set : function (name, value, day ) { let oDate = new Date () oDate.setDate (oDate.getDate () + (day || 30 )) document .cookie = name + '=' + value + ';expires=' + oDate + "; path=/;" }, get : function (name ) { let str = document .cookie let arr = str.split ('; ' ) for (let i = 0 ; i < arr.length ; i++) { let newArr = arr[i].split ('=' ) if (newArr[0 ] === name) { return newArr[1 ] } } }, del : function (name ) { this .set (name, '' , -1 ) } }
数字格式化单位 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 export function numberFormatter (num, digits ) { const si = [{ value : 1E18 , symbol : 'E' }, { value : 1E15 , symbol : 'P' }, { value : 1E12 , symbol : 'T' }, { value : 1E9 , symbol : 'G' }, { value : 1E6 , symbol : 'M' }, { value : 1E3 , symbol : 'k' } ] for (let i = 0 ; i < si.length ; i++) { if (num >= si[i].value ) { return (num / si[i].value ).toFixed (digits).replace (/\.0+$|(\.[0-9]*[1-9])0+$/ , '$1' ) + si[i].symbol } } return num.toString () }
数字千位过滤 1 2 3 4 5 6 7 8 9 10 11 12 13 export function toThousandFilter (num ) { let targetNum = (num || 0 ).toString () if (targetNum.includes ('.' )) { let arr = num.split ('.' ) return arr[0 ].replace (/^-?\d+/g , m => m.replace (/(?=(?!\b)(\d{3})+$)/g , ',' )) + '.' + arr[1 ] } else { return targetNum.replace (/^-?\d+/g , m => m.replace (/(?=(?!\b)(\d{3})+$)/g , ',' )) } }
过滤成版本号 1 2 3 4 5 6 7 8 9 10 11 12 export function versionFilter (versions ) { let v0 = (versions & 0xff000000 ) >> 24 let v1 = (versions & 0xff0000 ) >> 16 let v2 = (versions & 0xff00 ) >> 8 let v3 = versions & 0xff return `${v0} .${v1} .${v2} .${v3} ` }
首字母大写 1 2 3 4 5 6 7 export function uppercaseFirst (string ) { return string.charAt (0 ).toUpperCase () + string.slice (1 ) }
class骚操作 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 export function hasClass (ele, cls ) { return !!ele.className .match (new RegExp ('(\\s|^)' + cls + '(\\s|$)' )) } export function addClass (ele, cls ) { if (!hasClass (ele, cls)) ele.className += ' ' + cls } export function removeClass (ele, cls ) { if (hasClass (ele, cls)) { const reg = new RegExp ('(\\s|^)' + cls + '(\\s|$)' ) ele.className = ele.className .replace (reg, ' ' ) } }
文本复制功能 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 const copyTxt = function (text, fn ) { if (typeof document .execCommand !== 'function' ) { console .log ('复制失败,请长按复制' ) return } var dom = document .createElement ('textarea' ) dom.value = text dom.setAttribute ('style' , 'display: block;width: 1px;height: 1px;' ) document .body .appendChild (dom) dom.select () var result = document .execCommand ('copy' ) document .body .removeChild (dom) if (result) { console .log ('复制成功' ) typeof fn === 'function' && fn () return } if (typeof document .createRange !== 'function' ) { console .log ('复制失败,请长按复制' ) return } var range = document .createRange () var div = document .createElement ('div' ) div.innerhtml = text div.setAttribute ('style' , 'height: 1px;fontSize: 1px;overflow: hidden;' ) document .body .appendChild (div) range.selectNode (div) var selection = window .getSelection () console .log (selection) if (selection.rangeCount > 0 ) { selection.removeAllRanges () } selection.addRange (range) document .execCommand ('copy' ) typeof fn === 'function' && fn () console .log ('复制成功' ) }
判断是否是一个数组 1 2 3 4 export const castArray = value => (Array .isArray (value) ? value : [value])export const castArray = arr=> Object .prototype .toString .call (arr) === '[object Array]'
判断是否是一个空数组 1 2 3 4 export const isEmpty = (arr ) => !Array .isArray (arr) || arr.length === 0
克隆一个数组 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 const clone = (arr ) => arr.slice (0 );const clone = (arr ) => [...arr];const clone = (arr ) => Array .from (arr);const clone = (arr ) => arr.map ((x ) => x);const clone = (arr ) => JSON .parse (JSON .stringify (arr));const clone = (arr ) => arr.concat ([]);
数组去重 1 2 3 4 5 6 7 8 9 export const uniqueArray = (arr ) => Array .from (new Set (arr)) export const uniqueArray = (arr ) => arr.filter ((el, i, array ) => array.indexOf (el) === i)export const uniqueArray = (arr ) => arr.reduce ((acc, el ) => (acc.includes (el) ? acc : [...acc, el]), [])
是否为PC端 1 2 3 4 5 6 7 8 9 10 11 12 export const isPC = function ( ) { let userAgentInfo = navigator.userAgent let Agents = ['Android' , 'iPhone' , 'SymbianOS' , 'Windows Phone' , 'iPad' , 'iPod' ] let flag = true for (let v = 0 ; v < Agents .length ; v++) { if (userAgentInfo.indexOf (Agents [v]) > 0 ) { flag = false break } } return flag }
判断是否为微信 1 2 3 4 5 6 7 export const isWx = ( ) => { var ua = window .navigator .userAgent .toLowerCase () if (ua.match (/MicroMessenger/i ) === 'micromessenger' ) { return true } return false }
设备判断:android、ios、web 1 2 3 4 5 6 7 8 9 10 export const isDevice = function ( ) { var ua = navigator.userAgent .toLowerCase () if (ua.match (/iPhone\sOS/i ) === 'iphone os' || ua.match (/iPad/i ) === 'ipad' ) { return 'iOS' } if (ua.match (/Android/i ) === 'android' ) { return 'Android' } return 'Web' }
常见正则校验 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 export const normalReg = (str, type ) => { switch (type) { case 'phone' : return /^1[3|4|5|6|7|8|9][0-9]{9}$/ .test (str); case 'tel' : return /^(0\d{2,3}-\d{7,8})(-\d{1,4})?$/ .test (str); case 'card' : return /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/ .test (str); case 'pwd' : return /^[a-zA-Z]\w{5,17}$/ .test (str) case 'postal' : return /[1-9]\d{5}(?!\d)/ .test (str); case 'QQ' : return /^[1-9][0-9]{4,9}$/ .test (str); case 'email' : return /^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$/ .test (str); case 'money' : return /^\d*(?:\.\d{0,2})?$/ .test (str); case 'URL' : return /(http|ftp|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?/ .test (str) case 'IP' : return /((?:(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d)\\.){3}(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d))/ .test (str); case 'date' : return /^(\d{4})\-(\d{2})\-(\d{2}) (\d{2})(?:\:\d{2}|:(\d{2}):(\d{2}))$/ .test (str) || /^(\d{4})\-(\d{2})\-(\d{2})$/ .test (str) case 'number' : return /^[0-9]$/ .test (str); case 'positiveInteger' : return /^[1-9]\d*$/ .test (str); case 'price' : return /(^[1-9]\d*(\.\d{1,2})?$)|(^0(\.\d{1,2})?$)/ .test (str); case 'english' : return /^[a-zA-Z]+$/ .test (str); case 'chinese' : return /^[\u4E00-\u9FA5]+$/ .test (str); case 'lower' : return /^[a-z]+$/ .test (str); case 'upper' : return /^[A-Z]+$/ .test (str); case 'HTML' : return /<("[^"]*"|'[^']*'|[^'">])*>/ .test (str); default : return true ; } }
去除字符串空格 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 export const trim = function (str, type ) { type = type || 1 switch (type) { case 1 : return str.replace (/\s+/g , '' ) case 2 : return str.replace (/(^\s*)|(\s*$)/g , '' ) case 3 : return str.replace (/(^\s*)/g , '' ) case 4 : return str.replace (/(\s*$)/g , '' ) default : return str } }
过滤html代码 1 2 3 4 5 6 7 export const filterTag = function (str ) { str = str.replace (/&/ig , '&' ) str = str.replace (/</ig , '<' ) str = str.replace (/>/ig , '>' ) str = str.replace (' ' , ' ' ) return str }
生成随机数范围 1 2 3 4 5 6 7 export const random = function (min, max ) { if (arguments .length === 2 ) { return Math .floor (min + Math .random () * ((max + 1 ) - min)) } else { return null } }
判断图片加载完成 1 2 3 4 5 6 7 8 9 10 11 12 13 export const imgLoadAll = function (arr, callback ) { let arrImg = [] for (let i = 0 ; i < arr.length ; i++) { let img = new Image () img.src = arr[i] img.onload = function ( ) { arrImg.push (this ) if (arrImg.length == arr.length ) { callback && callback () } } } }
光标所在位置插入字符 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 export const insertAtCursor = function (dom, val ) { if (document .selection ) { dom.focus () let sel = document .selection .createRange () sel.text = val sel.select () } else if (dom.selectionStart || dom.selectionStart == '0' ) { let startPos = dom.selectionStart let endPos = dom.selectionEnd let restoreTop = dom.scrollTop dom.value = dom.value .substring (0 , startPos) + val + dom.value .substring (endPos, dom.value .length ) if (restoreTop > 0 ) { dom.scrollTop = restoreTop } dom.focus () dom.selectionStart = startPos + val.length dom.selectionEnd = startPos + val.length } else { dom.value += val dom.focus () } }
图片地址转base64 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 export const getBase64 = function (img ) { let getBase64Image = function (img, width, height ) { let canvas = document .createElement ("canvas" ); canvas.width = width ? width : img.width ; canvas.height = height ? height : img.height ; let ctx = canvas.getContext ("2d" ); ctx.drawImage (img, 0 , 0 , canvas.width , canvas.height ); let dataURL = canvas.toDataURL (); return dataURL; } let image = new Image (); image.crossOrigin = '' ; image.src = img; let deferred = $.Deferred (); if (img) { image.onload = function ( ) { deferred.resolve (getBase64Image (image)); } return deferred.promise (); } }
base64图片下载功能 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 export const downloadFile = (base64, fileName ) => { let base64ToBlob = (code ) => { let parts = code.split (';base64,' ); let contentType = parts[0 ].split (':' )[1 ]; let raw = window .atob (parts[1 ]); let rawLength = raw.length ; let uInt8Array = new Uint8Array (rawLength); for (let i = 0 ; i < rawLength; ++i) { uInt8Array[i] = raw.charCodeAt (i); } return new Blob ([uInt8Array], { type : contentType }); }; let aLink = document .createElement ('a' ); let blob = base64ToBlob (base64); let evt = document .createEvent ("HTMLEvents" ); evt.initEvent ("click" , true , true ); aLink.download = fileName; aLink.href = URL .createObjectURL (blob); aLink.click (); }
浏览器是否支持webP格式图片 1 export const webPBool = ( ) => !![].map && document .createElement ('canvas' ).toDataURL ('image/webp' ).indexOf ('data:image/webp' ) == 0
H5软键盘缩回、弹起回调 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 export function (downCb, upCb ) { var clientHeight = window .innerHeight downCb = typeof downCb === 'function' ? downCb : function ( ) {} upCb = typeof upCb === 'function' ? upCb : function ( ) {} window .addEventListener ('resize' , () => { var height = window .innerHeight if (height === clientHeight) { downCb () } if (height < clientHeight) { upCb () } }) }
对象属性剔除 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 function omit (object, props=[] ){ let res = {} Object .keys (object).forEach (key => { if (props.includes (key) === false ){ res[key] = typeof object[key] === 'object' && object[key] !== null ? jsON.parse (jsON.stringify (object[key])) : object[key] } }) return res } let data = { id : 1 , title : '12345' , name : '男' }omit (data, ['id' ])
深拷贝 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 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 }
函数防抖 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 export function debounce (func, wait, immediate ) { let timeout, args, context, timestamp, result const later = function ( ) { const last = +new Date () - timestamp if (last < wait && last > 0 ) { timeout = setTimeout (later, wait - last) } else { timeout = null if (!immediate) { result = func.apply (context, args) if (!timeout) context = args = null } } } return function (...args ) { context = this timestamp = +new Date () const callNow = immediate && !timeout if (!timeout) timeout = setTimeout (later, wait) if (callNow) { result = func.apply (context, args) context = args = null } return result } }
函数节流 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 export function (func, wait ,type ) { if (type===1 ){ let previous = 0 ; }else if (type===2 ){ let timeout; } return function ( ) { let context = this ; let args = arguments ; if (type===1 ){ let now = Date .now (); if (now - previous > wait) { func.apply (context, args); previous = now; } }else if (type===2 ){ if (!timeout) { timeout = setTimeout (() => { timeout = null ; func.apply (context, args) }, wait) } } } }
推荐阅读