/** * @description 工具函数集合 * @author wangfupeng */ class NavUA { public _ua: string // 是否为旧版 Edge public isOldEdge: boolean // 是否为 Firefox public isFirefox: boolean constructor() { this._ua = navigator.userAgent const math = this._ua.match(/(Edge?)\/(\d+)/) this.isOldEdge = math && math[1] == 'Edge' && parseInt(math[2]) < 19 ? true : false this.isFirefox = /Firefox\/\d+/.test(this._ua) && !/Seamonkey\/\d+/.test(this._ua) ? true : false } // 是否为 IE public isIE() { return 'ActiveXObject' in window } // 是否为 webkit public isWebkit() { return /webkit/i.test(this._ua) } } // 和 UA 相关的属性 export const UA = new NavUA() /** * 获取随机字符 * @param prefix 前缀 */ export function getRandom(prefix: string = ''): string { return prefix + Math.random().toString().slice(2) } /** * 替换 html 特殊字符 * @param html html 字符串 */ export function replaceHtmlSymbol(html: string) { return html .replace(//gm, '>') .replace(/"/gm, '"') .replace(/(\r\n|\r|\n)/g, '
') } export function replaceSpecialSymbol(value: string) { return value .replace(/</gm, '<') .replace(/>/gm, '>') .replace(/"/gm, '"') } interface Obj { [key: string]: unknown [key: number]: unknown } interface ArrObj { length: number [key: number]: unknown } /** * 遍历对象或数组,执行回调函数 * @param obj 对象或数组 * @param fn 回调函数 (key, val) => {...} */ export function forEach]>( obj: T, fn: (key: string, value: V) => boolean | void ): void export function forEach( obj: T, fn: (key: string, value: T[Extract]) => boolean | void ): void export function forEach( obj: T, fn: (key: string, value: T[Extract]) => boolean | void ): void export function forEach( obj: T, fn: ( key: string, value: T[Extract] | T[Extract] ) => boolean | void ): void { for (let key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { const result = fn(key, obj[key]) if (result === false) { // 提前终止循环 break } } } } /** * 遍历类数组 * @param fakeArr 类数组 * @param fn 回调函数 */ export function arrForEach( fakeArr: T, fn: (this: T, item: T[number], index: number) => boolean | unknown ): void { let i, item, result const length = fakeArr.length || 0 for (i = 0; i < length; i++) { item = fakeArr[i] result = fn.call(fakeArr, item, i) if (result === false) { break } } } /** * 节流 * @param fn 函数 * @param interval 间隔时间,毫秒 */ export function throttle( fn: (this: C, ...args: T) => unknown, interval: number = 200 ) { let flag = false return function (this: C, ...args: T): void { if (!flag) { flag = true setTimeout(() => { flag = false fn.call(this, ...args) // this 报语法错误,先用 null }, interval) } } } /** * 防抖 * @param fn 函数 * @param delay 间隔时间,毫秒 */ export function debounce( fn: (this: C, ...args: T) => void, delay: number = 200 ): (this: C, ...args: T) => void { let lastFn = 0 return function (...args: T) { if (lastFn) { window.clearTimeout(lastFn) } lastFn = window.setTimeout(() => { lastFn = 0 fn.call(this, ...args) // this 报语法错误,先用 null }, delay) } } /** * isFunction 是否是函数 * @param fn 函数 */ export function isFunction(fn: any): fn is Function { return typeof fn === 'function' } /** * 引用与非引用值 深拷贝方法 * @param data */ export function deepClone(data: T): T { if (typeof data !== 'object' || typeof data == 'function' || data === null) { return data } let item: any if (Array.isArray(data)) { item = [] } if (!Array.isArray(data)) { item = {} } for (let i in data) { if (Object.prototype.hasOwnProperty.call(data, i)) { item[i] = deepClone(data[i]) } } return item } /** * 将可遍历的对象转换为数组 * @param data 可遍历的对象 */ export function toArray(data: T) { return Array.prototype.slice.call(data) } /** * 唯一id生成 * @param length 随机数长度 */ export function getRandomCode() { return Math.random().toString(36).slice(-5) } /** * hex color 转换成 rgb * @param hex string */ export function hexToRgb(hex: string) { const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex) if (result == null) return null const colors = result.map(i => parseInt(i, 16)) const r = colors[1] const g = colors[2] const b = colors[3] return `rgb(${r}, ${g}, ${b})` }