Skip to content

工具函数

@erp/common 提供的工具函数集合,涵盖类型判断、防抖节流、对象操作、日期处理等常用功能。

功能分类

  • 类型判断 - isString / isNumber / isArray / isObject / isFunction
  • 防抖节流 - debounce / throttleByRaf
  • 对象操作 - omit / pick / getValueByPath
  • 日期处理 - dayjs / getNow / getDayjsValue
  • DOM 操作 - on / off / contains / scrollIntoView
  • 剪贴板 - clipboard

引入方式

typescript
import { 
  isString, isNumber, isArray, isObject,
  debounce, throttleByRaf,
  omit, pick,
  clipboard,
  dayjs
} from '@erp/common'

类型判断

isString

判断值是否为字符串。

typescript
isString(value: any): value is string

// 示例
isString('hello')  // true
isString(123)      // false
isString('')       // true

isNumber

判断值是否为数字(排除 NaN)。

typescript
isNumber(value: any): value is number

// 示例
isNumber(123)      // true
isNumber(0)        // true
isNumber(NaN)      // false
isNumber('123')    // false

isBoolean

判断值是否为布尔值。

typescript
isBoolean(value: unknown): value is boolean

// 示例
isBoolean(true)    // true
isBoolean(false)   // true
isBoolean(1)       // false
isBoolean('true')  // false

isArray

判断值是否为数组。

typescript
isArray(value: any): value is any[]

// 示例
isArray([])        // true
isArray([1, 2])    // true
isArray({})        // false
isArray('array')   // false

isObject

判断值是否为普通对象。

typescript
isObject<T>(value: T): value is Extract<T, Record<string, any>>

// 示例
isObject({})           // true
isObject({ a: 1 })     // true
isObject([])           // false
isObject(null)         // false
isObject(new Date())   // false

isFunction

判断值是否为函数。

typescript
isFunction(value: any): value is (...args: any[]) => any

// 示例
isFunction(() => {})       // true
isFunction(function() {})  // true
isFunction(class {})       // true
isFunction({})             // false

isNull

判断值是否为 null。

typescript
isNull(value: any): value is null

// 示例
isNull(null)       // true
isNull(undefined)  // false
isNull(0)          // false

isUndefined

判断值是否为 undefined。

typescript
isUndefined(value: any): value is undefined

// 示例
isUndefined(undefined)  // true
isUndefined(null)       // false
isUndefined(void 0)     // true

isPromise

判断值是否为 Promise。

typescript
isPromise<T>(value: unknown): value is Promise<T>

// 示例
isPromise(Promise.resolve())     // true
isPromise(new Promise(() => {})) // true
isPromise({ then: () => {} })    // false

isDate

判断值是否为 Date 对象。

typescript
isDate(value: any): boolean

// 示例
isDate(new Date())     // true
isDate('2024-01-01')   // false
isDate(Date.now())     // false

isRegExp

判断值是否为正则表达式。

typescript
isRegExp(value: any): boolean

// 示例
isRegExp(/test/)           // true
isRegExp(new RegExp('a'))  // true
isRegExp('/test/')         // false

isColor

判断值是否为有效的颜色值(支持 HEX、RGB、RGBA)。

typescript
isColor(value: any): boolean

// 示例
isColor('#fff')              // true
isColor('#ffffff')           // true
isColor('rgb(255,255,255)')  // true
isColor('rgba(0,0,0,0.5)')   // true
isColor('red')               // false

isEmptyValue

判断值是否为空值。

typescript
isEmptyValue(value: any): boolean

// 空值定义:
// - 字符串:空字符串或只有空格
// - 数组:空数组或元素全为 null/undefined
// - 对象:空对象
// - 数字:NaN
// - null 或 undefined

// 示例
isEmptyValue('')           // true
isEmptyValue('   ')        // true
isEmptyValue([])           // true
isEmptyValue([null])       // true
isEmptyValue({})           // true
isEmptyValue(NaN)          // true
isEmptyValue(null)         // true
isEmptyValue(undefined)    // true
isEmptyValue(0)            // false
isEmptyValue('0')          // false
isEmptyValue([0])          // false

isEmptyObject

判断值是否为空对象。

typescript
isEmptyObject(value: any): boolean

// 示例
isEmptyObject({})          // true
isEmptyObject({ a: 1 })    // false
isEmptyObject([])          // false

isExist

判断值是否存在(非空且非 undefined,但 0 视为存在)。

typescript
isExist(value: any): boolean

// 示例
isExist(0)         // true
isExist('')        // false
isExist(null)      // false
isExist(undefined) // false
isExist('hello')   // true

isWindow

判断值是否为 window 对象。

typescript
isWindow(value: any): value is Window

// 示例
isWindow(window)   // true
isWindow(document) // false

isDayjs

判断值是否为 dayjs 对象。

typescript
isDayjs(value: any): value is Dayjs

// 示例
import { dayjs } from '@erp/common'

isDayjs(dayjs())           // true
isDayjs(new Date())        // false
isDayjs('2024-01-01')      // false

防抖节流

debounce

防抖函数,在指定延迟时间内只执行最后一次调用。

typescript
debounce(callback: (...args: any[]) => void, delay: number): (...args: any[]) => void

// 示例
const handleSearch = debounce((keyword: string) => {
  console.log('搜索:', keyword)
}, 300)

// 快速连续调用,只会执行最后一次
handleSearch('a')
handleSearch('ab')
handleSearch('abc')  // 300ms 后执行

使用场景:

  • 搜索框输入
  • 窗口 resize 事件
  • 按钮防重复点击

throttleByRaf

基于 requestAnimationFrame 的节流函数,适用于动画和滚动场景。

typescript
throttleByRaf(
  callback: (...args: any[]) => void, 
  options?: { trailing?: boolean; leading?: boolean }
): { (...args: any[]): void; cancel: () => void }

// 示例
const handleScroll = throttleByRaf(() => {
  console.log('滚动位置:', window.scrollY)
})

window.addEventListener('scroll', handleScroll)

// 取消节流
handleScroll.cancel()

使用场景:

  • 滚动事件处理
  • 拖拽位置更新
  • 动画帧更新

对象操作

omit

从对象中排除指定的属性,返回新对象。

typescript
omit<T, K>(object: T, keys: K[]): Omit<T, K>

// 示例
const user = { id: 1, name: '张三', password: '123456', age: 25 }

omit(user, ['password'])
// { id: 1, name: '张三', age: 25 }

omit(user, ['password', 'age'])
// { id: 1, name: '张三' }

pick

从对象中选取指定的属性,返回新对象。

typescript
pick<T, K>(object: T, keys: K[]): Pick<T, K>

// 示例
const user = { id: 1, name: '张三', password: '123456', age: 25 }

pick(user, ['id', 'name'])
// { id: 1, name: '张三' }

pick(user, ['name', 'age'])
// { name: '张三', age: 25 }

getValueByPath

根据路径获取对象中的值。

typescript
import { getValueByPath } from '@erp/common'

const obj = {
  user: {
    profile: {
      name: '张三',
      address: {
        city: '北京'
      }
    }
  }
}

getValueByPath(obj, 'user.profile.name')
// '张三'

getValueByPath(obj, 'user.profile.address.city')
// '北京'

getValueByPath(obj, 'user.profile.phone')
// undefined

数组操作

toArray

将值转换为数组。

typescript
import { toArray } from '@erp/common'

toArray('hello')      // ['hello']
toArray(['a', 'b'])   // ['a', 'b']
toArray(undefined)    // []
toArray(null)         // []

剪贴板

clipboard

复制文本到剪贴板。

typescript
clipboard(text: string): Promise<void>

// 示例
import { clipboard } from '@erp/common'

// 复制文本
await clipboard('Hello World')

// 在按钮点击中使用
const handleCopy = async () => {
  try {
    await clipboard('要复制的内容')
    console.log('复制成功')
  } catch (error) {
    console.error('复制失败', error)
  }
}

日期处理

dayjs

内置的 dayjs 实例,已扩展常用插件。

typescript
import { dayjs } from '@erp/common'

// 基础用法
dayjs()                          // 当前时间
dayjs('2024-01-01')              // 解析日期
dayjs().format('YYYY-MM-DD')     // 格式化
dayjs().add(1, 'day')            // 加一天
dayjs().subtract(1, 'month')     // 减一月

// 已加载的插件
// - customParseFormat: 自定义解析格式
// - isBetween: 判断是否在范围内
// - weekOfYear: 获取周数
// - advancedFormat: 高级格式化
// - weekYear: 周年
// - quarterOfYear: 季度

getNow

获取当前时间的 dayjs 对象。

typescript
import { getNow } from '@erp/common'

const now = getNow()
console.log(now.format('YYYY-MM-DD HH:mm:ss'))

getDayjsValue

将日期值转换为 dayjs 对象。

typescript
import { getDayjsValue } from '@erp/common'

// 单个值
getDayjsValue('2024-01-01', 'YYYY-MM-DD')
// Dayjs 对象

// 数组
getDayjsValue(['2024-01-01', '2024-12-31'], 'YYYY-MM-DD')
// [Dayjs, Dayjs]

getDateValue

将 dayjs 对象转换为 Date 对象。

typescript
import { getDateValue, dayjs } from '@erp/common'

getDateValue(dayjs())
// Date 对象

getDateValue([dayjs(), dayjs().add(1, 'day')])
// [Date, Date]

DOM 操作

on / off

添加/移除事件监听器。

typescript
import { on, off } from '@erp/common'

const handleClick = (e: MouseEvent) => {
  console.log('clicked', e)
}

// 添加事件
on(document.body, 'click', handleClick)

// 移除事件
off(document.body, 'click', handleClick)

contains

判断一个节点是否包含另一个节点。

typescript
import { contains } from '@erp/common'

contains(parentElement, childElement)
// true 或 false

getElement

根据选择器或元素获取 DOM 元素。

typescript
import { getElement } from '@erp/common'

getElement('#app')           // 通过 ID
getElement('.container')     // 通过类名
getElement(domElement)       // 直接返回元素

getRelativeRect

获取两个元素之间的相对位置。

typescript
import { getRelativeRect } from '@erp/common'

const rect = getRelativeRect(targetElement, relativeElement)
// { top, bottom, left, right, width, height }

isScroll

判断元素是否可滚动。

typescript
import { isScroll } from '@erp/common'

isScroll(element)  // true 或 false

getScrollBarWidth

获取滚动条宽度。

typescript
import { getScrollBarWidth } from '@erp/common'

const width = getScrollBarWidth(element)

getParentScroller

获取元素的滚动父容器。

typescript
import { getParentScroller } from '@erp/common'

const scroller = getParentScroller(element)

checkElInView

检查元素是否在可视区域内。

typescript
import { checkElInView } from '@erp/common'

// 检查元素是否在窗口可视区域
checkElInView(element)

// 检查元素是否在指定容器可视区域
checkElInView(element, containerElement)

// 带预加载因子
checkElInView(element, window, 1.5)

滚动

scrollIntoView

将元素滚动到可视区域。

typescript
import { scrollIntoView } from '@erp/common'

scrollIntoView(element, {
  behavior: 'smooth',  // 平滑滚动
  block: 'center',     // 垂直居中
  inline: 'nearest'    // 水平最近
})

computeScrollIntoView

计算滚动到可视区域所需的滚动量。

typescript
import { computeScrollIntoView } from '@erp/common'

const actions = computeScrollIntoView(element, {
  block: 'center',
  inline: 'nearest'
})
// 返回需要执行的滚动操作数组

弹出层

getPopupStyle

获取弹出层的定位样式。

typescript
import { getPopupStyle } from '@erp/common'

const style = getPopupStyle(triggerRect, popupRect, position)

getElementScrollRect

获取元素相对于滚动容器的位置。

typescript
import { getElementScrollRect } from '@erp/common'

const rect = getElementScrollRect(element, containerRect)

基于 MIT 许可发布