| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239 | /** * @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(/"/gm, '"')        .replace(/(\r\n|\r|\n)/g, '<br/>')}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<T extends ArrObj, V = T[Extract<keyof T, number>]>(    obj: T,    fn: (key: string, value: V) => boolean | void): voidexport function forEach<T extends Obj>(    obj: T,    fn: (key: string, value: T[Extract<keyof T, string | number>]) => boolean | void): voidexport function forEach<T extends unknown[]>(    obj: T,    fn: (key: string, value: T[Extract<keyof T, number>]) => boolean | void): voidexport function forEach<T extends unknown[] | Obj | ArrObj>(    obj: T,    fn: (        key: string,        value: T[Extract<keyof T, number>] | T[Extract<keyof T, string>]    ) => 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<T extends { length: number; [key: number]: unknown }>(    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<C, T extends unknown[]>(    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<C, T extends unknown[]>(    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<T>(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<T>(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})`}
 |