时间格式转换
使用方法:parseTime(1622536859864,"{y}-{m}-{d} {h}:{i}")
输出:"2021-06-01 16:40:59"
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)) {
time = parseInt(time);
} else if (/T/g.test(time)) {
time = new Date(time);
} else {
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];
if (key === "a") {
return ["日", "一", "二", "三", "四", "五", "六"][value];
}
return value.toString().padStart(2, "0");
});
return time_str;
}
过去距离当前时间格式转换
使用方法:formatTime(1622536859864);
输出:6分钟前
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()
.toString()
.padStart(2, "0")
);
}
}
获取指定或者URL参数
使用方法:getQueryObject("https://www.baidu.com?channel=weixin");
输出:{channel: "weixin"}
/**
* @param {string} url
* @returns {Object}
*/
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
}
获取字符串字节长度
使用方法:byteLength("hello,沉默术士");
输出:18
export function byteLength(str) {
let s = str.length;
for (var i = str.length - 1; i >= 0; i--) {
const code = str.charCodeAt(i);
if (code > 0x7f && code <= 0x7ff) s++;
else if (code > 0x7ff && code <= 0xffff) s += 2;
if (code >= 0xdc00 && code <= 0xdfff) i--;
}
return s;
}
合并两个纯对象
/**
*
* @param {Object} target
* @param {(Object|Array)} source
* @returns {Object}
*/
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
}
切换样式
/**
* @param {HTMLElement} element
* @param {string} className
*/
export function toggleClass(element, className) {
if (!element || !className) {
return
}
let classString = element.className
const nameIndex = classString.indexOf(className)
if (nameIndex === -1) {
classString += "" + className
} else {
classString =
classString.substr(0, nameIndex) +
classString.substr(nameIndex + className.length)
}
element.className = classString
}
函数防抖
export function debounce(func, wait, immediate) {
let timeout, args, context, timestamp, result
const later = function() {
// 据上一次触发时间间隔
const last = +new Date() - timestamp
// 上次被包装函数被调用时间间隔 last 小于设定时间间隔 wait
if (last < wait && last > 0) {
timeout = setTimeout(later, wait - last)
} else {
timeout = null
// 如果设定为immediate===true,因为开始边界已经调用过了此处无需调用
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
}
}
函数节流
export function throttle(func, wait) {
var timeout;
return function() {
var _this = this,
args = arguments;
if (!timeout) {
timeout = setTimeout(() => {
timeout = null;
func.apply(_this, args);
}, wait);
}
};
}
深克隆
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;
}
数组去重
export function uniqueArr(arr) {
return Array.from(new Set(arr));
}
唯一字符串
export function createUniqueString() {
const timestamp = +new Date() + "";
const randomNum = parseInt((1 + Math.random()) * 65536) + "";
return (+(randomNum + timestamp)).toString(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, " ")
}
}
判断终端类型
export function getClient(){
const ua = navigator.userAgent;
let env = {
ua: ua,
isMobile: /android|iphone|ipod|ipad/i.test(ua),
isIOS: /iphone|ipod|ipad|ios|mac os/i.test(ua),
isAndroid: /android/i.test(ua),
isWechat: /micromessenger/i.test(ua),
isQQ: /qq\//i.test(ua),
isWeibo: /weibo/i.test(ua),
isDingTalk: /dingtalk/i.test(ua)
};
env.isBrowser = !(
env.isWechat ||
env.isQQ ||
env.isWeibo ||
env.isDingTalk
);
return env;
}
判断是否是纯对象
var _toString = Object.prototype.toString;
function isPlainObject(obj) {
return _toString.call(obj) === "[object Object]";
}
数字类型转换
function toNumber(val) {
var n = parseFloat(val);
return isNaN(n) ? val : n;
}
判断两个数据类型是否是非严格相等
function looseEqual(a, b) {
if (a === b) {
return true;
}
var isObjectA = isObject(a);
var isObjectB = isObject(b);
if (isObjectA && isObjectB) {
try {
var isArrayA = Array.isArray(a);
var isArrayB = Array.isArray(b);
if (isArrayA && isArrayB) {
return (
a.length === b.length &&
a.every(function (e, i) {
return looseEqual(e, b[i]);
})
);
} else if (a instanceof Date && b instanceof Date) {
return a.getTime() === b.getTime();
} else if (!isArrayA && !isArrayB) {
var keysA = Object.keys(a);
var keysB = Object.keys(b);
return (
keysA.length === keysB.length &&
keysA.every(function (key) {
return looseEqual(a[key], b[key]);
})
);
} else {
return false;
}
} catch (e) {
return false;
}
} else if (!isObjectA && !isObjectB) {
return String(a) === String(b);
} else {
return false;
}
}
只调用一次函数
function once(fn) {
var called = false
return function () {
if (!called) {
called = true
fn.apply(this, arguments)
}
}
}
数字格式化
/**
* Number formatting
* like 10000 => 1万
* @param {number} num
* @param {number} digits
*/
export function numberFormatter(num, digits = 2, round) {
const si = [
{
value: 1e9,
symbol: "亿"
},
{
value: 1e4,
symbol: "万"
}
]
for (let i = 0
if (num >= si[i].value) {
if (round) {
return (
String(
Math.floor((num / si[i].value) * Math.pow(10,digits)) / Math.pow(10,digits)
).replace(/\.0+$|(\.[0-9]*[1-9])0+$/, "$1") + si[i].symbol
)
} else {
return (
(num / si[i].value)
.toFixed(digits)
.replace(/\.0+$|(\.[0-9]*[1-9])0+$/, "$1") + si[i].symbol
)
}
}
}
return num.toFixed(digits)
}
数字千位数格式化
export function toThousandFilter(num, digits = 2) {
return (+num || 0)
.toFixed(digits)
.replace(/^-?\d+/g, m => m.replace(/(?=(?!\b)(\d{3})+$)/g, ","));
}
字符串首字母大写
export function uppercaseFirst(string) {
return string.charAt(0).toUpperCase() + string.slice(1);
}