@qisexin/utils-tool v1.5.3
🛠️ @qisexin/utils-tool
🚀 个人前端工具库,将工作中常用的方法封装成小函数,持续丰富中
English | 简体中文
📖 目录
🚀 安装
# npm
npm install @qisexin/utils-tool
# yarn
yarn add @qisexin/utils-tool
# pnpm
pnpm add @qisexin/utils-tool📦 快速开始
// ES6 模块导入
import { toThousands, getQueryString } from '@qisexin/utils-tool';
// 使用示例
const formattedNumber = toThousands(1234567.89); // "1,234,567.89"
const urlParam = getQueryString('id'); // 获取URL参数// CommonJS 导入
const { toThousands, getQueryString } = require('@qisexin/utils-tool');
// 按需导入(推荐)
import { toThousands } from '@qisexin/utils-tool/formatNumber';
import { getQueryString } from '@qisexin/utils-tool/other';
// Antd 工具导入
import { CopyToClipboard, downloadExcel } from '@qisexin/utils-tool/antd-utils';
// Hooks 导入
import { useLocalStorageState } from '@qisexin/utils-tool/hooks';✨ 项目特点
📚 API 文档
🔤 字符串处理
encodeValue(val: string): string
编码字符串中的特殊字符,将特殊字符转换为 URL 编码格式
参数:
val(string): 需要编码的字符串
返回值: string - 编码后的字符串
encodeValue('test?name=value') // => 'test%3Fname%3Dvalue'
encodeValue('hello world') // => 'hello%20world'decodeValue(val: string): string
解码字符串中的特殊字符,将 URL 编码格式转换为原始字符
参数:
val(string): 需要解码的字符串
返回值: string - 解码后的字符串
decodeValue('test%3Fname%3Dvalue') // => 'test?name=value'
decodeValue('hello%20world') // => 'hello world'getActualWidthOfChars(text: string, options?: { font?: string }): number
通过 Canvas 获取字符串的实际像素宽度,支持自定义字体
参数:
text(string): 需要测量的文本options(object, 可选): 配置选项font(string, 可选): 字体样式,默认为 '12px Arial'
返回值: number - 文本的像素宽度
getActualWidthOfChars('Hello World') // => 66
getActualWidthOfChars('性能数据', { font: '14px Microsoft YaHei' }) // => 56generateRandomColor(): string[]
生成随机颜色数组,返回 10 个随机的 RGB 颜色值
返回值: string[] - 包含 10 个 RGB 颜色字符串的数组
generateRandomColor()
// => ['rgb(48, 62, 6)', 'rgb(123, 45, 67)', 'rgb(200, 100, 150)', ...]getRandomKey(): string
生成随机的唯一标识符,基于时间戳和随机数
返回值: string - 随机生成的唯一标识符
getRandomKey() // => '1701234567890_abc123'
getRandomKey() // => '1701234567891_def456'🔢 数字处理
toThousands(x: number, digits?: number): string
将数字转换为千位分隔符格式,支持指定小数位数
参数:
x(number): 需要格式化的数字digits(number, 可选): 小数位数,默认保持原有精度
返回值: string - 格式化后的字符串
toThousands(1234567.89) // => "1,234,567.89"
toThousands(1234567.123, 2) // => "1,234,567.12"
toThousands(1000) // => "1,000"convertSpecialNumbers(num: number): number
处理特殊数字值,将 NaN 和 Infinity 转换为 0
参数:
num(number): 需要处理的数字
返回值: number - 处理后的数字
convertSpecialNumbers(NaN) // => 0
convertSpecialNumbers(Infinity) // => 0
convertSpecialNumbers(-Infinity) // => 0
convertSpecialNumbers(123) // => 123convertEmptyNumber(num: any): string | number
处理空值数字显示,0 显示为 0,null/undefined 显示为 '--'
参数:
num(any): 需要处理的值
返回值: string | number - 处理后的显示值
convertEmptyNumber(null) // => '--'
convertEmptyNumber(undefined) // => '--'
convertEmptyNumber(0) // => 0
convertEmptyNumber(123) // => 123bytesConverter(bytes: number, unit: string): string
字节单位转换,将字节数转换为指定单位
参数:
bytes(number): 字节数unit(string): 目标单位 ('B', 'KB', 'MB', 'GB', 'TB')
返回值: string - 转换后的字符串(包含单位)
bytesConverter(1024, 'KB') // => '1KB'
bytesConverter(4 * 1024 * 1024, 'MB') // => '4MB'
bytesConverter(1073741824, 'GB') // => '1GB'📦 对象处理
encodeObject(obj: Record<string, any>): Record<string, any>
递归编码对象中所有字符串值的特殊字符
参数:
obj(Record<string, any>): 需要编码的对象
返回值: Record<string, any> - 编码后的新对象
encodeObject({ name: 'hello world', desc: 'test?value' })
// => { name: 'hello%20world', desc: 'test%3Fvalue' }decodeObject(obj: Record<string, any>): Record<string, any>
递归解码对象中所有字符串值的特殊字符
参数:
obj(Record<string, any>): 需要解码的对象
返回值: Record<string, any> - 解码后的新对象
decodeObject({ name: 'hello%20world', desc: 'test%3Fvalue' })
// => { name: 'hello world', desc: 'test?value' }escapeRegExpObject(obj: Record<string, any>): Record<string, any>
转义对象中所有字符串值的正则表达式特殊字符
参数:
obj(Record<string, any>): 需要转义的对象
返回值: Record<string, any> - 转义后的新对象
escapeRegExpObject({ pattern: '[test]', regex: '(.*?)' })
// => { pattern: '\\[test\\]', regex: '\\(\\.\\*\\?\\)' }replaceKeys<T>(obj: T, keysMap: Record<string, string>): T
根据映射表替换对象或数组中的键名
参数:
obj(T): 需要处理的对象或数组keysMap(Record<string, string>): 键名映射表
返回值: T - 替换键名后的新对象或数组
replaceKeys({ oldKey: 'value' }, { oldKey: 'newKey' })
// => { newKey: 'value' }
replaceKeys([{ a: 1 }, { a: 2 }], { a: 'b' })
// => [{ b: 1 }, { b: 2 }]⏰ 日期时间
checkAndCompleteDate(dateString: string): string
检查日期字符串格式,如果没有时分秒则自动补充 23:59:59
参数:
dateString(string): 日期字符串
返回值: string - 完整的日期时间字符串
checkAndCompleteDate('2023-12-01') // => '2023-12-01 23:59:59'
checkAndCompleteDate('2023-12-01 10:30:00') // => '2023-12-01 10:30:00'showDuration(options: { startTime: string; endTime: string; language?: 'zh' | 'en' }): string
计算并格式化两个时间点之间的时长
参数:
options(object): 配置选项startTime(string): 开始时间endTime(string): 结束时间language('zh' | 'en', 可选): 语言,默认为 'zh'
返回值: string - 格式化的时长字符串
showDuration({
startTime: '2023-12-01 10:00:00',
endTime: '2023-12-01 13:30:45'
}) // => '3小时30分钟45秒'
showDuration({
startTime: '2023-12-01 10:00:00',
endTime: '2023-12-01 13:30:45',
language: 'en'
}) // => '3h30m45s'formatUUID(uuidStr: string): string
将 32 位 UUID 字符串转换为标准的带连字符格式
参数:
uuidStr(string): 32 位 UUID 字符串
返回值: string - 标准格式的 UUID 字符串
formatUUID('550e8400e29b41d4a716446655440000')
// => '550e8400-e29b-41d4-a716-446655440000'🌐 DOM 操作
copyToClipboard(text: string): Promise<void>
复制文本到剪贴板,支持现代浏览器的 Clipboard API
参数:
text(string): 需要复制的文本
返回值: Promise<void> - 复制操作的 Promise
await copyToClipboard('Hello World')
copyToClipboard('https://example.com').then(() => {
console.log('复制成功')
})scrollToAnchor(anchorName: string): void
平滑滚动到指定的锚点元素
参数:
anchorName(string): 锚点元素的 ID
返回值: void
scrollToAnchor('section1') // 滚动到 id="section1" 的元素
scrollToAnchor('top') // 滚动到 id="top" 的元素🔗 URL 处理
getQueryString(name: string): string | null
从当前页面 URL 中获取指定参数的值
参数:
name(string): 参数名
返回值: string | null - 参数值,不存在时返回 null
// 当前 URL: https://example.com?id=123&name=test
getQueryString('id') // => '123'
getQueryString('name') // => 'test'
getQueryString('notexist') // => nullurlParamsToObject(url: string): Record<string, string>
将 URL 中的查询参数转换为对象
参数:
url(string): 完整的 URL 字符串
返回值: Record<string, string> - 参数对象
urlParamsToObject('https://example.com?id=123&name=test&active=true')
// => { id: '123', name: 'test', active: 'true' }objectToUrlParams(params: Record<string, any>): string
将对象转换为 URL 查询参数字符串
参数:
params(Record<string, any>): 参数对象
返回值: string - URL 参数字符串
objectToUrlParams({ id: 123, name: 'test', active: true })
// => 'id=123&name=test&active=true'🛠️ 工具函数
mixedSort(a: any, b: any): number
中英文数字混合排序比较函数,排序优先级:数字 > 英文字母 > 中文拼音
参数:
a(any): 第一个比较值b(any): 第二个比较值
返回值: number - 比较结果 (-1, 0, 1)
const arr = ['中文', '1', 'apple', '2', '测试', 'banana']
arr.sort(mixedSort)
// => ['1', '2', 'apple', 'banana', '测试', '中文']📊 Echarts 工具
largeDataTooltipOptimization(params: any, labelField: string, rowsPerColumn: number, defaultColumnWidth: number): string
优化 Echarts 大数据量下的 Tooltip 显示,支持多列布局
参数:
params(any): Echarts tooltip 的 params 参数labelField(string): 用作标签的字段名rowsPerColumn(number): 每列显示的行数defaultColumnWidth(number): 默认列宽(像素)
返回值: string - 格式化的 HTML 字符串
// 在 Echarts 配置中使用
const option = {
tooltip: {
formatter: (params) => largeDataTooltipOptimization(
params,
'deviceName',
10,
200
)
}
}🎨 Antd 相关工具
⚠️ 注意: 使用 antd-utils 时,需要在项目中安装
react、react-dom、antd,并从@qisexin/utils-tool/antd-utils内引入方法
CopyToClipboard 组件
复制到剪贴板的 React 组件,基于 Antd 的 Button 组件
Props:
copyText(string): 需要复制的文本内容children(ReactNode): 按钮显示内容- 其他 Antd Button 组件支持的 props
import { CopyToClipboard } from '@qisexin/utils-tool/antd-utils';
// 基础用法
<CopyToClipboard copyText="需要复制的内容">
点击复制
</CopyToClipboard>
// 自定义样式
<CopyToClipboard
copyText="https://example.com"
type="primary"
size="small"
>
复制链接
</CopyToClipboard>downloadExcel
基础的 Excel 文件下载功能
函数签名:
downloadExcel(data: any[], filename?: string): void参数:
data(any[]): 要导出的数据数组filename(string, 可选): 文件名,默认为 'export.xlsx'
import { downloadExcel } from '@qisexin/utils-tool/antd-utils';
const data = [
{ name: '张三', age: 25, city: '北京' },
{ name: '李四', age: 30, city: '上海' }
];
downloadExcel(data, '用户列表.xlsx');downloadXlsxPro
高级 Excel 文件下载功能,支持复杂样式定制、多工作表、合并单元格等
主要特性:
- ✅ 支持多工作表
- ✅ 支持单元格样式定制(字体、颜色、边框等)
- ✅ 支持合并单元格
- ✅ 支持列宽自适应
- ✅ 支持数据类型转换
- ✅ 支持自定义表头
详细使用方法请参考:downloadXlsxPro 文档
getColumnSearchProps
为 Antd Table 添加本地搜索功能的高阶函数
函数签名:
getColumnSearchProps(dataIndex: string, searchInput?: RefObject<InputRef>): ColumnType<any>参数:
dataIndex(string): 要搜索的列字段名searchInput(RefObject, 可选): 搜索输入框的 ref
返回值: ColumnType<any> - Antd Table 列配置对象
import { getColumnSearchProps } from '@qisexin/utils-tool/antd-utils';
import { useRef } from 'react';
import type { InputRef } from 'antd';
const MyTable = () => {
const searchInput = useRef<InputRef>(null);
const columns = [
{
title: '姓名',
dataIndex: 'name',
key: 'name',
width: '30%',
...getColumnSearchProps('name', searchInput),
},
{
title: '年龄',
dataIndex: 'age',
key: 'age',
...getColumnSearchProps('age'),
}
];
return <Table columns={columns} dataSource={data} />;
};🪝 自定义 Hooks
useLocalStorageState
将状态存储在 localStorage 中的 Hook,支持跨标签页通信和 SSR
函数签名:
useLocalStorageState<T>(
key: string,
defaultValue?: T | (() => T),
options?: {
defaultValue?: T | (() => T);
serializer?: Serializer<T>;
onError?: (error: Error) => void;
}
): [T, (value: T | ((prevState: T) => T)) => void]参数:
key(string): localStorage 的键名defaultValue(T | (() => T), 可选): 默认值或默认值工厂函数options(object, 可选): 配置选项defaultValue(T | (() => T), 可选): 默认值(优先级高于第二个参数)serializer(Serializer, 可选): 自定义序列化器onError((error: Error) => void, 可选): 错误处理函数
返回值: [T, (value: T | ((prevState: T) => T)) => void] - 状态值和设置函数
import { useLocalStorageState } from '@qisexin/utils-tool/hooks';
// 基础用法
const [count, setCount] = useLocalStorageState('count', 0);
// 使用对象
const [user, setUser] = useLocalStorageState('user', {
name: '',
age: 0
});
// 自定义配置
const [theme, setTheme] = useLocalStorageState('theme', 'light', {
onError: (error) => {
console.error('localStorage error:', error);
}
});
// 函数式更新
setCount(prev => prev + 1);🤝 贡献指南
欢迎提交 Issue 和 Pull Request!
- Fork 本仓库
- 创建你的特性分支 (
git checkout -b feature/AmazingFeature) - 提交你的修改 (
git commit -m 'Add some AmazingFeature') - 推送到分支 (
git push origin feature/AmazingFeature) - 打开一个 Pull Request
📄 许可证
本项目基于 MIT 许可证开源。
🔗 相关链接
如果这个工具库对你有帮助,请给个 ⭐️ 支持一下!