工作中常常很多数据处理操作需要公用,于是抽离出来变为一个个函数,用起来很香,但是由于比较多,手写呢嫌麻烦,这就记一记,以便日后用时ctrl cv一把嗦。
原来只有本篇,再补充一篇
【CSDN】常用JS工具类函数 | 上 (本文)
【CSDN】常用JS工具类函数 | 下
大家都是面向百度编程(手动狗头)🐶,来来来,要就拿走
文章目录
时间
dayjs
或者moment
能做很多事情了
时间戳转化为天时分,倒计时时可使用
说明: time为时间戳
const timeDef = end.getTime() - nowTime.getTime()
const dates = formatDuring(timeDef)
function formatDuring(time){
const st = Number(time);
const day = parseInt((st / (1000 * 3600 * 24)).toString());
const hour = parseInt(((st % (1000 * 3600 * 24)) / (1000 * 3600)).toString())
const minute = parseInt(((st % (1000 * 3600))/(1000 * 60)).toString())
return [day,hour, minute]
}
// formatDuring(new Date('2020-07-18 20:00').getTime() - new Date('2020-07-17 19:10').getTime())
// [1, 0, 50]
时间转为年月日时分
//传入new Date()
function convertTime(date) {
let res = '';
if(date.getFullYear()) {
const y = date.getFullYear();
const mo = date.getMonth() + 1 > 10 ? date.getMonth() + 1 : '0'+(date.getMonth()+1)
const d = date.getDate();
const h = date.getHours() > 10 ? date.getHours(): '0'+date.getHours();
const m = date.getMinutes() > 10 ? date.getMinutes(): '0'+date.getMinutes();
res = y+"/"+mo+"/"+d+" "+h+":"+m;
}
return res;
}
// convertTime(new Date()) "2021/07/17 20:24"
格式化时间
function dateFormater(formater, t){
let date = t ? new Date(t) : new Date(),
Y = date.getFullYear() + '',
M = date.getMonth() + 1,
D = date.getDate(),
H = date.getHours(),
m = date.getMinutes(),
s = date.getSeconds();
return formater.replace(/YYYY|yyyy/g,Y)
.replace(/YY|yy/g,Y.substr(2,2))
.replace(/MM/g,(M<10?'0':'') + M)
.replace(/DD/g,(D<10?'0':'') + D)
.replace(/HH|hh/g,(H<10?'0':'') + H)
.replace(/mm/g,(m<10?'0':'') + m)
.replace(/ss/g,(s<10?'0':'') + s)
}
// dateFormater('YYYY-MM-DD HH:mm', t) ==> 2019-06-26 18:30
// dateFormater('YYYYMMDDHHmm', t) ==> 201906261830
当前范围值直至多少天后(前)的值
说明: range 前面给’-'返回多少天前,否则多少天后,Delimiter 分隔符
function getDateTime(range, Delimiter = "-") {
const date = [];
const now = new Date();
const rangeStr = range.toString();
if(rangeStr.indexOf("-") === -1){
date[0] = now.toLocaleDateString().replace(/\//g, Delimiter);
date[1] = new Date(now.setDate(now.getDate() + Number(rangeStr)))
.toLocaleDateString().replace(/\//g, Delimiter);
}
else {
date[0] = new Date(now.setDate(now.getDate() - Number(rangeStr.split("-")[1])))
.toLocaleDateString().replace(/\//g, Delimiter)
date[1] = new Date().toLocaleDateString().replace(/\//g, Delimiter);
}
return date;
}
// 今天到未来五天
// getDateTime(5, '-=')
// ["2021-=7-=17", "2021-=7-=22"]
返回两个时间戳相差的天数
这个与 时间戳转化为天时分,倒计时时可使用
有点重复
function dateDiffs(start, end){
const sTime = new Date(start).getTime(),
eTime = new Date(end).getTime();
if(sTime && eTime) {
return Math.floor((eTime - sTime)/(1000*3600*24))
}
else {
throw new Error("传入的日期格式错误")
}
}
// dateDiffs('2021-07-1', '2021-07-08')
// 7
转换时间(今日,明日,几月几日转为标准时间)
这是我在思否一个问题下的 回答
function formatTime(dateStr = '') {
if(dateStr) {
const dateMatch = dateStr.replace(/^(([月\d]{3,5})|([前今明后]))日(\s[0-9:]{8})$/, (match, p1, p2, p3, time) => {
let date = ''
if(p1.length === 1) {
const dateMap = {
'前': -2,
'昨': -1,
'明': 1
};
const count = dateMap[p1] || 0;
const today = new Date().getDate()
const dateNum = today + count;
const current = new Date();
current.setDate(dateNum);
date = new Date(current).toLocaleDateString();
}else {
const year = new Date().getFullYear();
const mon = p1.split('月')[0];
const day = p1.split('月')[1];
const current = new Date()
current.setMonth(mon - 1);
current.setDate(day);
date = new Date(current).toLocaleDateString();
}
const resStr = date + time;
const str = new Date(date + time).toLocaleString()
console.log('end: ', dateStr, ' => ', str);
return str;
})
return dateMatch
}
}
console.log(formatTime('明日 10:30:40')); // 2023/6/2 10:30:40
console.log(formatTime('今日 14:00:08')); // 2023/6/1 14:00:08
console.log(formatTime('6月8日 17:07:16')); // 2023/6/8 17:07:16
// 稍微有些特殊的情况
console.log(formatTime('0月1日 17:07:16')); //2022/12/1 17:07:16
console.log(formatTime('12月35日 17:07:16')); // 2024/1/4 17:07:16
console.log(formatTime('13月3日 17:07:16')); // 2024/1/3 17:07:16
获取当前日期的周一、周末的日期
export function getWeeekdata(cdate){ //cdate 传来当前的时间
let now = new Date(cdate);
let year = now.getFullYear();
let month = now.getMonth() + 1;
let date = now.getDate();
let nowTime = now.getTime();
let day = now.getDay();
let oneDayTime = 24 * 60 * 60 * 1000;
if(day==0){
var MondayTime = nowTime - 6 * oneDayTime;
var SundayTime = nowTime;
}else if(day==1){
var MondayTime = nowTime;
var SundayTime = nowTime + (7 - day) * oneDayTime;
}else{
var MondayTime = nowTime - (day - 1) * oneDayTime;
//显示周日
var SundayTime = nowTime + (7 - day) * oneDayTime;
}
//初始化日期时间
var monday = new Date(MondayTime);
var sunday = new Date(SundayTime);
return [format(monday), format(sunday)];
}
function format(date) {
var time = new Date(date);
var y = time.getFullYear();
var m =
time.getMonth() + 1 < 10 ? "0" + (time.getMonth() + 1) : time.getMonth() + 1;
var d = time.getDate() < 10 ? "0" + time.getDate() : time.getDate();
//var h = time.getHours();
//var mm = time.getMinutes();
//var s = time.getSeconds();
return y + "-" + m + "-" + d;
}
根据当前时间获取当月的1号和最后一号
export function getcurentMonth(cdate) { //cdate传来的当前的时间
// 当天
let thatDay = "";
// 当月第一天
let oneDayTime = "";
// 当月最后一天
let zDay = "";
let date = new Date(cdate);
let curr_date = date.getDate();
let curr_month = date.getMonth() + 1;
let curr_year = date.getFullYear();
String(curr_month).length < 2 ? (curr_month = "0" + curr_month) : curr_month;
String(curr_date).length < 2 ? (curr_date = "0" + curr_date) : curr_date;
thatDay = curr_year + "-" + curr_month + "-" + curr_date;
String(curr_year).length < 2 ? (curr_year = "0" + curr_year) : curr_year;
var m = date.getMonth() + 1;
String(m).length < 2 ? (m = "0" + m) : m;
var d = "01";
oneDayTime = curr_year + "-" + m + "-" + d;
//结束时间
var currentMonth = date.getMonth();
var nextMonth = ++currentMonth;
var nextMonthFirstDay = new Date(date.getFullYear(), nextMonth, 1);
var oneDay = 1000 * 60 * 60 * 24;
var date1 = new Date(nextMonthFirstDay - oneDay);
var yy = date1.getFullYear();
String(yy).length < 2 ? (yy = "0" + yy) : yy;
var mm = date1.getMonth() + 1;
String(mm).length < 2 ? (mm = "0" + mm) : mm;
var dd = date1.getDate();
String(dd).length < 2 ? (dd = "0" + dd) : dd;
zDay = yy + "-" + mm + "-" + dd;
return [thatDay, oneDayTime, zDay];
}
对象
深度克隆(仅支持数组、对象等)
//深克隆的递归实现
export function deepClone(target) {
//判断拷贝的数据类型
//初始化变量result 成为最终克隆的数据
function checkedType(targets: objectData | arrayData): string {
return Object.prototype.toString.call(targets).slice(8, -1)
}
let result, targetType: string = checkedType(target)
if (targetType === 'Object') {
result = {}
} else if (targetType === 'Array') {
result = [];
} else {
return target
}
//遍历目标数据
for (let i in target) {
let value = target[i]
if (checkedType(value) === 'Object' ||
checkedType(value) === 'Array') {
result[i] = deepClone(value)
} else {
result[i] = value;
}
}
return result
}
清空对象值
// 这个有点鸡肋
export function clearForm(obj: objectData): objectData {
const object: objectData = new Object();
for(let k in obj) {
if(Object.prototype.toString.call(obj[k]) === '[object Object]')
object[k] = {};
else if(Object.prototype.toString.call(obj[k]) === '[object Array]')
object[k] = [];
else object[k] = "";
}
return object;
}
其他
去驼峰
推荐 JS 正则迷你书⇲
function reverseHump(k){
return k.replace(/([A-Z])/g, '_$1').replace(/[-_\s]+/g, '_').toLowerCase();
}
// reverseHump('airBox') => "air_box"
驼峰化
function hump(k){
return k.replace(/[-_\s]+(.)?/g, function(match,c) {
return c? c.toUpperCase() : "";
});
}
// hump('air_Box') => "airBox"
转换
kb转更大单位(Mb, Gb等)
function formatSizeUnits(kb) {
let units = ['KB', 'MB', 'GB', 'TB', 'PB'];
let unitIndex = 0;
while (kb >= 1024 && unitIndex < units.length - 1) {
kb /= 1024;
unitIndex++;
}
return `${kb.toFixed(2)} ${units[unitIndex]}`;
}
防抖
想要了解更多防抖节流 可参考
防抖01
短时间多次执行只执行一次
/**
func 回调函数
wait 等待时间
immediate {boolean} 是否立即值执行
*/
function debounce(func, wait, immediate) {
var timeout, result;
var debounced = function () {
var context = this;
var args = arguments;
if (timeout) clearTimeout(timeout);
if (immediate) {
// 如果已经执行过,不再执行
var callNow = !timeout;
timeout = setTimeout(function(){
timeout = null;
}, wait)
if (callNow) result = func.apply(context, args)
} else {
timeout = setTimeout(function(){
func.apply(context, args)
}, wait);
}
return result;
};
debounced.cancel = function() {
clearTimeout(timeout);
timeout = null;
};
return debounced;
}
防抖02 vue装饰器使用版本
/**
func 回调函数
wait 等待时间
immediate {boolean} 是否立即值执行
*/
export class Debounced {
/**
* @param func 需要包装的函数
* @param delay 延迟时间,单位ms
* @param immediate 是否默认执行一次(第一次不延迟)
*/
public use = (func: Function, delay: number, immediate: boolean = false): Function => {
let timer: number | undefined
return ( ...args: any) => {
if (immediate) {
func.apply(this, args) // 确保引用函数的指向正确,并且函数的参数也不变
immediate = false
return
}
clearTimeout(timer)
timer = setTimeout(() => {
func.apply(this, args)
}, delay)
}
}
}
xxx.vue
使用
private debouncedBySatus = new Debounced().use(this.getOrders, 1000, true);
// 用@click = “handleEvent”
private handleEvent(){
//.....
this.debouncedBySatus();
}
节流
频繁触发,单位时间 wait
内执行一次, 支持
- 支持立即执行;
- 函数可能有返回值;
- 支持取消功能;
/**
func 回调函数
wait 等待时间
options { leading , trailing } 立即执行,尾调用
*/
function throttle(func, wait, options) {
var timeout, context, args, result;
var previous = 0;
if (!options) options = {};
var later = function() {
previous = options.leading === false ? 0 : new Date().getTime();
timeout = null;
func.apply(context, args);
if (!timeout) context = args = null;
};
var throttled = function() {
var now = new Date().getTime();
if (!previous && options.leading === false) previous = now;
var remaining = wait - (now - previous);
context = this;
args = arguments;
if (remaining <= 0 || remaining > wait) {
if (timeout) {
clearTimeout(timeout);
timeout = null;
}
previous = now;
func.apply(context, args);
if (!timeout) context = args = null;
} else if (!timeout && options.trailing !== false) {
timeout = setTimeout(later, remaining);
}
};
throttled.cancel = function() {
clearTimeout(timeout);
previous = 0;
timeout = null;
}
return throttled;
}
检测数据类型
// 返回 Object/Array
function checkedType(targets) {
return Object.prototype.toString.call(targets).slice(8, -1)
}
// checkedType({}) "Object"
// checkedType([]) "Array"
cookie处理
const getCookie = (key) => {
const reg = new RegExp('\\b'+key+'=([^;]+)(;|$)','i');// '/\b'+key+'=([^;]+)'+value+'(;|$)'/i'
let val = document.cookie.match(reg);
return val ? val[1]: '';
};
const setCookie = (c_name,value,expiredays) => {
let exdate=new Date();
exdate.setDate(exdate.getDate()+expiredays);
document.cookie=c_name+ "=" +value+
((expiredays==null) ? "" : ";expires="+exdate.toDateString())
};
const delCookie = (name) => {
setCookie(name,'',-1);
};
setTimeOut定时任务的实现
模拟 setinterval
,但是此次任务完成才执行下一次任务。
//setTimeOut模拟定时器
let timer = null;
let count = 0;
function plus(){ count++; conole.log('任务被执行 ', count) }
function t1(){
// alert(1)
console.log('done', count);
return new Promise((resolve) => {
setTimeout(() => {
plus() // resolve可能在plus内部,确定plus结束,才会重新等待执行下一次任务
resolve(1)
}, 6000);
})
}
async function mocker(){
const res = await t1();
if(timer !== null) clearTimeout(timer);
if(res) timer = setTimeout(mocker, 5000);
}
mocker();
首字母大写
function firstUpper(str = ''){
return str.toLowerCase().replace(/( |^)[a-z]/g, (s) => s.toUpperCase());
}
图片压缩
function compressImg(file) {
return new Promise(resolve => {
let reader = new FileReader();
let ndata;
// 将图片2将转成 base64 格式
reader.readAsDataURL(file);
// 读取成功后的回调
reader.onloadend = function () {
let result = this.result;
let img = new Image();
img.src = result;
img.onload = function () {
ndata = compress(img);
//BASE64转图片
const arr = ndata.split(',');
const mime = arr[0].match(/:(.*?);/)[1];
const bstr = atob(arr[1]);
let n = bstr.length;
const u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
ndata = new File([u8arr], file.name, { type: mime })
resolve({ flag: 1, file: ndata })
}
}
})
}
function compress(img) {
let canvas = document.createElement("canvas");
let ctx = canvas.getContext('2d');
//瓦片canvas
let tCanvas = document.createElement("canvas");
let tctx = tCanvas.getContext("2d");
let initSize = img.src.length;
let width = img.width;
let height = img.height;
//如果图片大于四百万像素,计算压缩比并将大小压至400万以下
let ratio;
if ((ratio = width * height / 4000000) > 1) {
ratio = Math.sqrt(ratio);
width /= ratio;
height /= ratio;
} else {
ratio = 1;
}
canvas.width = width;
canvas.height = height;
// 铺底色
ctx.fillStyle = "#fff";
ctx.fillRect(0, 0, canvas.width, canvas.height);
//如果图片像素大于100万则使用瓦片绘制
let count;
if ((count = width * height / 1000000) > 1) { // 超过100W像素
count = ~~(Math.sqrt(count) + 1); //计算要分成多少块瓦片
// 计算每块瓦片的宽和高
let nw = ~~(width / count);
let nh = ~~(height / count);
tCanvas.width = nw;
tCanvas.height = nh;
for (let i = 0; i < count; i++) {
for (let j = 0; j < count; j++) {
tctx.drawImage(img, i * nw * ratio, j * nh * ratio, nw * ratio, nh * ratio, 0, 0, nw, nh);
ctx.drawImage(tCanvas, i * nw, j * nh, nw, nh);
}
}
} else {
ctx.drawImage(img, 0, 0, width, height);
}
//进行最小压缩
let ndata = canvas.toDataURL('image/jpeg', 0.1);
console.log('压缩前:' + initSize);
console.log('压缩后kb:' + ndata.length/1024);
console.log("ndata:" + ndata)
console.log('压缩率:' + ~~(100 * (initSize - ndata.length) / initSize) + "%");
tCanvas.width = tCanvas.height = canvas.width = canvas.height = 0;
return ndata;
}
图片懒加载
与常规的相比增加了
- 图片全部加载完成后移除事件监听;
- 加载完的图片,从 imgList 移除;
let imgList = [...document.querySelectorAll('img')]
let length = imgList.length
const imgLazyLoad = function() {
let count = 0
return (function() {
let deleteIndexList = []
imgList.forEach((img, index) => {
let rect = img.getBoundingClientRect()
if (rect.top < window.innerHeight) {
img.src = img.dataset.src
deleteIndexList.push(index)
count++
if (count === length) {
document.removeEventListener('scroll', imgLazyLoad)
}
}
})
imgList = imgList.filter((img, index) => !deleteIndexList.includes(index))
})()
}
// 这里最好加上防抖处理
document.addEventListener('scroll', imgLazyLoad)
将url解析为对象
function parseParam(url) {
const paramsStr = /.+\?(.+)$/.exec(url)[1]; // 将 ? 后面的字符串取出来
const paramsArr = paramsStr.split('&'); // 将字符串以 & 分割后存到数组中
let paramsObj = {};
// 将 params 存到对象中
paramsArr.forEach(param => {
if (/=/.test(param)) { // 处理有 value 的参数
let [key, val] = param.split('='); // 分割 key 和 value
val = decodeURIComponent(val); // 解码
val = /^\d+$/.test(val) ? parseFloat(val) : val; // 判断是否转为数字
if (paramsObj.hasOwnProperty(key)) { // 如果对象有 key,则添加一个值
paramsObj[key] = [].concat(paramsObj[key], val);
} else { // 如果对象没有这个 key,创建 key 并设置值
paramsObj[key] = val;
}
} else { // 处理没有 value 的参数
paramsObj[param] = true;
}
})
return paramsObj;
}
// parseParam('http://www.baidu.com?name=李四&age=46&from=china')
// {name: "李四", age: 46, from: "china"}
或者当前 url
获取 url 指定的参数
function getQueryVariable(variable) {
const query = window.location.search.substring(1);
const vars = query.split("&");
for (let i = 0; i < vars.length; i++) {
const pair = vars[i].split("=");
if (pair[0] == variable) {
return pair[1];
}
}
return undefined;
}
其实一般工具类库
lodash
underscore
(记得好像是这个) 都有的 尽 量 用库。
文件
判断文件上传的类型
/**
* @param: fileName - 文件名称
* @param: 数据返回 1) 无后缀匹配 - false
* @param: 数据返回 2) 匹配图片 - image
* @param: 数据返回 3) 匹配 txt - txt
* @param: 数据返回 4) 匹配 excel - excel
* @param: 数据返回 5) 匹配 word - word
* @param: 数据返回 6) 匹配 pdf - pdf
* @param: 数据返回 7) 匹配 ppt - ppt
* @param: 数据返回 8) 匹配 视频 - video
* @param: 数据返回 9) 匹配 音频 - radio
* @param: 数据返回 10) 其他匹配项 - other
* @author: ljw
**/
export function fileSuffixTypeUtil(fileName){
// 后缀获取
var suffix = "";
// 获取类型结果
var result = "";
try {
var flieArr = fileName.split(".");
suffix = flieArr[flieArr.length - 1];
} catch (err) {
suffix = "";
}
// fileName无后缀返回 false
if (!suffix) {
result = false;
return result;
}
// 图片格式
var imglist = ["png", "jpg", "jpeg", "bmp", "gif"];
// 进行图片匹配
result = imglist.some(function (item) {
return item == suffix;
});
if (result) {
result = "image";
return result;
}
// 匹配txt
var txtlist = ["txt"];
result = txtlist.some(function (item) {
return item == suffix;
});
if (result) {
result = "txt";
return result;
}
// 匹配 excel
var excelist = ["xls", "xlsx"];
result = excelist.some(function (item) {
return item == suffix;
});
if (result) {
result = "excel";
return result;
}
// 匹配 word
var wordlist = ["doc", "docx"];
result = wordlist.some(function (item) {
return item == suffix;
});
if (result) {
result = "word";
return result;
}
// 匹配 pdf
var pdflist = ["pdf"];
result = pdflist.some(function (item) {
return item == suffix;
});
if (result) {
result = "pdf";
return result;
}
// 匹配 ppt
var pptlist = ["ppt"];
result = pptlist.some(function (item) {
return item == suffix;
});
if (result) {
result = "ppt";
return result;
}
// 匹配 视频
var videolist = ["mp4", "m2v", "mkv"];
result = videolist.some(function (item) {
return item == suffix;
});
if (result) {
result = "video";
return result;
}
// 匹配 音频
var radiolist = ["mp3", "wav", "wmv"];
result = radiolist.some(function (item) {
return item == suffix;
});
if (result) {
result = "radio";
return result;
}
// 其他 文件类型
result = "other";
return result;
};
文件下载
/**
* @param: fileType - 文件类型
* @param: fileName - 文件名称
* @param: data - 数据流文件
**/
export function download(fileType, bucketName,data) {
let downType = "";
let downName = "";
if (fileType == "image") {
downType = "image/png";
downName = fileName + ".png";
} else if (fileType == "word") {
downType = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
downName = fileName + ".docx";
} else if (fileType == "video") {
downType = "video/mpeg4";
downName = fileName + ".mp4";
} else if (fileType == "radio") {
downType = "audio/mpeg";
downName = fileName + ".mp3";
} else if (fileType == "pdf") {
downType = "application/pdf";
downName = fileName + ".pdf";
}
let blob = new Blob([data], { type: downType });
let downloadElement = document.createElement("a");
let href = window.URL.createObjectURL(blob);
downloadElement.href = href;
document.body.appendChild(downloadElement);
//downloadElement.setAttribute("download", downName);//设置下载名称
downloadElement.download = downName; //设置下载文件名称
downloadElement.click();
document.body.removeChild(downloadElement); //移除元素;防止连续点击创建多个a标签
window.URL.revokeObjectURL(href);
}
参考
站在别人肩膀上能看的更远,感谢💖💖💖以下文章作者
【掘金】| JS兵法36 计,你会多少?⇲
js常用技巧汇总