项目常用值得收藏的JavaScript函数

171 阅读2分钟

前言

项目当中有各种公用的utils 方法需要整合,这里给大家分享几个比较好用的方法

1. 获取深层数据

/**
 * 提取深层数据的值 (防止中间项 不存在导致的报错)
 * @param obj any 数据源
 * @param keyArr string|number[] key数组
 * @returns any
 */
export function getDeepValue(obj, keyArr) {
    return keyArr.reduce((acc, key) => acc && acc[key], obj)
}

// eg:
var res = {
    a: {
        list: [{name: 'item1', id: '1'}]
    },
    b: [
        {name: 'b', id: 'b1', children: [{ name: 'b2', id: 'b2' }]}
    ]
}
getDeepValue(res, ['b', 0, 'children', 0, 'name']) // 'b2'
getDeepValue(res, ['a', 'list', 0, 'name']) // 'item1'

2. 自定义log打印

/**
 * @param content 数据源
 * @param title string
 * @param background string
 */
export function custLog(content, title = 'title', background = '#007bfc') {
    content = typeof content === 'object' ? JSON.stringify(content) : content
    console.log.apply(null, [
        `%c ${title}: %c ${content} `,
        'padding: 1px; border-radius: 10px; color: #fff; background: #9159B2;',
        `padding: 1px; border-radius: 10px; color: #fff; background: ${background};`
    ])
}

custLog({a: [{b: 'b'}], c: 123})
custLog('自定义', 'custTitle', 'orange') 

打印引用数据
custLog
打印字符串 title声明
image.png

3. 函数防抖/节流

  • 防抖:指定时间内 频繁触发一个事件,只触发最后一次
  • 节流:指定时间内 频繁触发一个事件,只会触发一次
/**
 * @desc 函数防抖
 * @param func 函数
 * @param wait number 延迟毫秒数
 * @param immediate boolean 立即执行
 */
export function debounce(func, wait = 1000, immediate = false) {
    let timeout
    const _clear = () => {  
        clearTimeout(timeout)  
        timeout = null  
    }
    return function () {
        const bool = !timeout
        if (immediate && bool) func.apply(this, arguments)
        if (timeout) _clear()
        timeout = setTimeout(function () {
            func.apply(this, arguments)
        }, wait)
        if (bool) _clear()
    }
}

/**
 * @desc 函数防抖
 * @param func 函数
 * @param wait number 延迟毫秒数
 * @param immediate boolean 立即执行
 */
export function throttle(func, wait = 1000, immediate = false) {
    let t_start = 0
    return function () {
        const args = arguments
        if (!t_start) {
            t_start = +new Date()
            if (immediate) func.apply(this, args)
        }
        const t_end = +new Date()
        if (t_end - t_start >= wait) {
            func.apply(this, args)
            t_start = t_end
        }
    }
}

4. 文字复制

/**
 * 复制文字
 * @param val
 * @returns {boolean}
 */
export function copyText(val) {
	const textarea = document.createElement('textarea')
	// 将该 textarea 设为 readonly 防止 iOS 下自动唤起键盘,同时将 textarea 移出可视区域
	textarea.readOnly = 'readonly'
	textarea.style.position = 'absolute'
	textarea.style.left = '-9999px'
	textarea.value = val
	document.body.appendChild(textarea)
	textarea.select()
	const res = document.execCommand('copy')
	document.body.removeChild(textarea)
	return res
}

5. 异步操作未完成前加锁

/**
 * 异步操作避免重复触发加锁
 * @param syncFn
 * @returns {(function(...[*]): Promise<void>)|*}
 */
export function asyncHandlerLockWrap(syncFn) {
	let is_lock = false
	return async function (...args) {
		const context = this
		if (!is_lock) {
			is_lock = true
			Promise.resolve()
				.then(syncFn.bind(context, ...args))
				.finally(() => {
					is_lock = false
				})
		}
	}
}

//eg: 点击按钮触发接口调用, 存在误操作或者恶意操作的情况时 等异步回调结束才允许再次触发
var btnClick = asyncHandlerLockWrap(() => {
    // 模拟调用接口
    return new Promise((s) => {
        setTimeout(s, 5000)
    }).then(() => {
        console.log('完成')
        return 'success'
    })
})
// <button onClick={btnClick}>提交</button>

6. formatNumber 转金额数字

/**
 * 转化成带逗号的number格式
 * @param num string|number
 * @param minimumFractionDigits 保留小数位
 * @returns {string}
 */
export function formatNumber(num, minimumFractionDigits = 0) {
    return (+num || 0).toLocaleString('zh', { minimumFractionDigits })
}

formatNumber(15, 2) // '15.00'
formatNumber(123456.3, 2) // '123,456.30'
formatNumber('123.45', 2) // '123.45'

推荐

分享给大家一个Vue3 + Ts + Element-plus & Vite 搭建,开箱即用的后台管理项目, 手机端已兼容,如果觉得不错希望可以得到各位大佬的star

文件地址: src/layout/components/CheckUpdates PC访问

PC访问2

手机端访问

项目链接 github.com/LanceJiang/…
访问链接 lancejiang.github.io/Lance-Eleme…