jsmethodutils
Version:
JS 常用方法总结
474 lines (461 loc) • 11.7 kB
JavaScript
/**
* @description: JS 常用方法封装
* @param {*} checkDataType 数据类型检查
* @param {*} randomNum 生成随机数,支持随机小数
* @param {*} easyArrRepetition 简单数组去重
* @param {*} complexArrRepetition 复杂数组去重
* @param {*} promiseAll 封装 Promise.all 遇到 reject 后,直接返回问题
* @param {*} dateFormat 秒级时间戳、毫秒级时间戳、日期对象 格式化时间
* @param {*} checkMobile 验证手机号格式是否正确
* @param {*} checkEmail 验证邮箱格式是否正确
* @param {*} checkPassword 验证密码格式是否正确 (必须为 6-20 个字符,而且同时包含字母和数字)
* @param {*} createRandomNum 生成n位随机数
* @param {*} toDecimal2 保留2位小数
* @param {*} createUuid 生成uuid
* @param {*} browserInfo 判断运行环境
* @param {*} detectOS 判断运行设备
* @param {*} throttle 节流(throttle)
* @param {*} debounce 防抖(debounce)
* @param {*} ThousandNum 格式化金钱
* @param {*} RandomId 生成随机ID
* @param {*} RandomColor 生成随机HEX色值
* @param {*} lazyLoad 懒加载
* @param {*} loadMore 加载更多
* @param {*} fixedToHeader 固定到顶部(吸顶)
*/
/**
* @description: JS 数据类型检查
* @param {*} content 检测值
* @param {*} Type 期待类型
* @return {*} Boolean
*/
export function checkDataType(content, Type) {
return Object.prototype.toString.call(content) === `[object ${Type}]`;
}
/**
* @description: 生成随机数,支持随机小数
* @param {*} min 最小值
* @param {*} max 最大值
* @param {*} point 几位小数,默认0
* @return {*} String
*/
export function randomNum(min = 0, max = 100, point = 0) {
if (point && point > 0) {
return (Math.random() * (max - min + 1) + min).toFixed(point);
}
return parseInt(Math.random() * (max - min + 1) + min);
}
/**
* @description 简单数组去重
* @param {*} arg 数组
* @returns Array
*/
export function easyArrRepetition(...arg) {
return [...new Set([...arg].flat(Infinity))];
}
/**
* @description 复杂数组去重
* @param key 根据key进行去重
* @param arg 数组
* @returns Array
*/
export function complexArrRepetition(key, ...arg) {
if (!key || typeof key !== "string") return new Error("请传入正确的key值");
let arr = [...arg].flat(Infinity);
let hash = {};
return arr.reduce((next, item) => {
hash[item[key]] ? "" : (hash[item[key]] = true && next.push(item));
return next;
}, []);
}
/**
* @description 封装 Promise.all 遇到 reject 后,直接返回问题
* @param arg promise数组
* @returns Promise
*/
export function promiseAll(...arg) {
return new Promise((resolve, reject) => {
const promiseAll = [...arg]
.flat(Infinity)
.map(
(item) =>
(Object.prototype.toString.call(item) ===
"[object Promise]" &&
item.catch((e) => e)) ||
item
);
Promise.all(promiseAll)
.then((res) => {
resolve(res);
})
.catch((err) => {
reject(err);
});
});
}
/**
* @description 秒级时间戳、毫秒级时间戳、日期对象 格式化时间
* @param date
* @param fmt
* @returns string
*/
export function dateFormat(date, fmt = "yyyy-MM-dd hh:mm:ss") {
let type = Object.prototype.toString.call(date);
if (type !== "[object Number]" && type !== "[object Date]") return;
if (type === "[object Number]")
date = new Date(
Number(date).toString().length === 10 ? date * 1000 : date
);
let o = {
"M+": date.getMonth() + 1, //月份
"d+": date.getDate(), //日
"h+": date.getHours(), //小时
"m+": date.getMinutes(), //分
"s+": date.getSeconds(), //秒
"q+": Math.floor((date.getMonth() + 3) / 3), //季度
S: date.getMilliseconds(), //毫秒
};
if (/(y+)/.test(fmt))
fmt = fmt.replace(
RegExp.$1,
(date.getFullYear() + "").substr(4 - RegExp.$1.length)
);
for (let k in o)
if (new RegExp("(" + k + ")").test(fmt))
fmt = fmt.replace(
RegExp.$1,
RegExp.$1.length === 1
? o[k]
: ("00" + o[k]).substr(("" + o[k]).length)
);
return fmt;
}
/**
* 验证手机号格式是否正确
*
* @export
* @param phone 手机号
* @returns boolean
*/
export function checkMobile(phone) {
let reg = /^1\d{10}$/;
return !!reg.test(phone);
}
/**
* 验证邮箱格式是否正确
*
* @export
* @param email 邮箱
* @returns boolean
*/
export function checkEmail(email) {
let reg = /^([a-zA-Z]|[0-9])(\w|\-)+@[a-zA-Z0-9]+\.([a-zA-Z]{2,4})$/;
return !!reg.test(email);
}
/**
* 验证密码格式是否正确 (必须为 6-20 个字符,而且同时包含字母和数字)
*
* @export
* @param {number} password 密码
* @returns
*/
export function checkPassword(password) {
let reg = /^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,20}$/;
return !!reg.test(password);
}
/**
* 生成随机数
*
* @export
* @param {number} n 随机数位数
* @returns
*/
export function createRandomNum(n) {
let rnd = "";
for (let i = 0; i < n; i++) {
rnd += Math.floor(Math.random() * 10);
}
return parseInt(rnd, 10);
}
/**
* 保留2位小数
*
* @export
* @param {number} n 0.00格式
* @returns
*/
export function toDecimal2(x) {
var f = parseFloat(x);
if (isNaN(f)) {
return false;
}
var f = Math.round(x * 100) / 100;
var s = f.toString();
var rs = s.indexOf(".");
if (rs < 0) {
rs = s.length;
s += ".";
}
while (s.length <= rs + 2) {
s += "0";
}
return s;
}
/**
* @description 生成uuid
*/
export function createUuid() {
let d = new Date().getTime();
let uuid = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(
/[xy]/g,
function (c) {
let r = (d + Math.random() * 16) % 16 | 0;
d = Math.floor(d / 16);
return (c === "x" ? r : (r & 0x3) | 0x8).toString(16);
}
);
return uuid;
}
/**
* @description 判断运行环境
*/
export function browserInfo() {
let ua = navigator.userAgent;
return {
isAndroid: Boolean(ua.match(/android/gi)),
isIphone: Boolean(ua.match(/iphone|ipod/gi)),
isIpad: Boolean(ua.match(/ipad/gi)),
isWeixin: Boolean(ua.match(/MicroMessenger/gi)),
isAli: Boolean(ua.match(/AlipayClient/gi)),
isPhone: Boolean(/(iPhone|iPad|iPod|iOS|Android)/i.test(ua)),
isApp: Boolean(/(zwwl-ios|zwwl-android)/i.test(ua)),
};
}
/**
* @description 判断运行设备
*/
export function detectOS() {
const { platform } = navigator;
const isWin =
platform.toLowerCase() == "win32" ||
platform.toLowerCase() == "windows";
const hasLinux = platform.toLowerCase().includes("linux");
const hasTouch = "ontouchend" in document;
if (isWin) return "Windows";
if (hasLinux) return "Pad";
if (hasTouch) {
return "iPad";
} else {
return "Mac";
}
}
/**
* @description: 节流(throttle)
* @param {*} fn
* @param {*} delay
* @return {*}
*/
export function throttle(fn, delay) {
let valid = true;
return function () {
if (!valid) {
return false;
}
valid = false;
setTimeout(() => {
fn && fn();
valid = true;
}, delay);
};
}
/**
* @description: 防抖(debounce)
* @param {*} fn
* @param {*} delay
* @return {*}
*/
export function debounce(fn, delay) {
let timer = null;
return function () {
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(fn, delay);
};
}
/**
* @description: JS 深拷贝
* @param {*} arg
* @return {*}
*/
export function deepClone(arg) {
return arg && JSON.parse(JSON.stringify(arg));
}
/**
* @description: 格式化金钱
* @param {*} num
* @return {*}
*/
export function thousandNum(num) {
const types = ["string", "number"];
if (!types.includes(typeof num)) return new Error("传入参数格式错误!");
return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
/**
* @description: 生成随机ID
* @param {*} len
* @return {*}
*/
export function RandomId(len = 6) {
const types = ["string", "number"];
if (!types.includes(typeof len)) return new Error("传入参数格式错误!");
return Math.random().toString(36).substr(3, len);
}
/**
* @description: 生成随机HEX色值
* @return {*}
*/
export function RandomColor() {
return (
"#" +
Math.floor(Math.random() * 0xffffff)
.toString(16)
.padEnd(6, "0")
);
}
/**
* @description: 懒加载
* @param {*} els 元素列表
* @param {*} preloadHeight 预加载高度
* @param {*} defaultSrc 渲染真实url标签属性名
* @return {*}
*/
export function lazyLoad(
els = [],
preloadHeight = 1000,
defaultSrc = "data-src"
) {
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
// 目标元素出现在 root 可视区,返回 true
const elTarget = entry.target;
const src = elTarget.getAttribute(defaultSrc);
src && elTarget.setAttribute("src", src); // 真正加载图片
observer.unobserve(elTarget); // 停止观察
}
});
},
{
rootMargin: `0px 0px ${preloadHeight}px 0px`,
threshold: 0.1, //触发目标元素可见的时机
}
);
Array.prototype.forEach.call(els, (el) => {
observer.observe(el); // 开始观察
});
}
/**
* @description: 加载更多
* @param {*} cb 触底后的回调函数
* @param {*} el 触底元素
* @return {*}
*/
export function loadMore(cb, el) {
if (!el || typeof el === "string") {
throw new Error("请传入一个触底的dom元素");
return;
}
const observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
cb();
}
});
});
observer.observe(el);
}
/**
* @description: 固定到顶部(吸顶)
* @param {*} fixedEl 顶部固定元素
* @param {*} observerEl 监听吸顶元素
* @param {*} className 固定到底部的className
* @return {*}
*/
export function fixedToHeader(fixedEl, observerEl, className) {
const observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (!entry.isIntersecting) {
className
? fixedEl.classList.add(className)
: (fixedEl.style.cssText =
"position: sticky; top: -1px; left: 0");
} else {
className
? fixedEl.classList.remove(className)
: (fixedEl.style.cssText = "");
}
});
});
observer.observe(observerEl);
}
/**
* @description: 非空判断
* @param {*} obj
* @return {*}
*/
export function isNotEmpty(obj) {
try {
if (obj == null || obj == undefined) {
return false;
}
//判断数字是否是NaN
if (typeof obj === "number") {
if (isNaN(obj)) {
return false;
} else {
return true;
}
}
//判断参数是否是布尔、函数、日期、正则,是则返回true
if (
typeof obj === "boolean" ||
typeof obj === "function" ||
obj instanceof Date ||
obj instanceof RegExp
) {
return true;
}
//判断参数是否是字符串,去空,如果长度为0则返回false
if (typeof obj === "string") {
if (obj.trim().length == 0) {
return false;
} else {
return true;
}
}
if (typeof obj === "object") {
//判断参数是否是数组,数组为空则返回false
if (obj instanceof Array) {
if (obj.length == 0) {
return false;
} else {
return true;
}
}
//判断参数是否是对象,判断是否是空对象,是则返回false
if (obj instanceof Object) {
//判断对象属性个数
if (Object.getOwnPropertyNames(obj).length == 0) {
return false;
} else {
return true;
}
}
}
} catch (e) {
console.log(e);
return false;
}
}