utils.ts
本地来源:模版/template/raphael-starterkit-v1-main/analysis/06-工具函数/utils.ts.md
工具函数详细分析
文件概述
lib/utils.ts 和 utils/utils.ts 包含项目中使用的核心工具函数,提供类名合并、数据格式化、验证等功能。
lib/utils.ts 分析
import { type ClassValue, clsx } from "clsx";
import { twMerge } from "tailwind-merge";
导入分析:
- ClassValue: clsx的类型定义,支持多种类名格式
- clsx: 条件类名处理库,用于动态类名组合
- twMerge: Tailwind CSS类名合并工具,智能处理冲突
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
类名合并函数:
- cn: classNames的缩写,项目中最常用的工具函数
- ...inputs: ClassValue[]: 支持多种输入格式的类名参数
- clsx(inputs): 先使用clsx处理条件逻辑和格式化
- twMerge(): 再使用twMerge智能合并Tailwind类名
使用示例
// 基础用法
cn('px-2 py-1', 'text-sm')
// 输出: "px-2 py-1 text-sm"
// 条件类名
cn('base-class', {
'active-class': isActive,
'disabled-class': isDisabled
})
// 冲突类名合并(twMerge的优势)
cn('px-2 px-4') // 输出: "px-4" (后者覆盖前者)
cn('text-red-500 text-blue-500') // 输出: "text-blue-500"
utils/utils.ts 分析
export function formatDate(date: Date | string): string {
const d = typeof date === 'string' ? new Date(date) : date;
return d.toLocaleDateString('zh-CN', {
year: 'numeric',
month: '2-digit',
day: '2-digit'
});
}
日期格式化函数: - 支持Date对象和字符串输入 - 使用中文本地化格式 - 返回YYYY-MM-DD格式
export function formatCurrency(amount: number, currency: string = 'CNY'): string {
return new Intl.NumberFormat('zh-CN', {
style: 'currency',
currency: currency,
minimumFractionDigits: 2,
maximumFractionDigits: 2
}).format(amount);
}
货币格式化函数: - 使用Intl.NumberFormat进行本地化 - 默认使用人民币(CNY) - 保留两位小数
export function debounce<T extends (...args: any[]) => any>(
func: T,
wait: number
): (...args: Parameters<T>) => void {
let timeout: NodeJS.Timeout;
return (...args: Parameters<T>) => {
clearTimeout(timeout);
timeout = setTimeout(() => func(...args), wait);
};
}
防抖函数: - 泛型实现,保持类型安全 - 使用setTimeout实现防抖逻辑 - 返回延迟执行的函数
export function throttle<T extends (...args: any[]) => any>(
func: T,
limit: number
): (...args: Parameters<T>) => void {
let inThrottle: boolean;
return (...args: Parameters<T>) => {
if (!inThrottle) {
func(...args);
inThrottle = true;
setTimeout(() => inThrottle = false, limit);
}
};
}
节流函数: - 限制函数执行频率 - 使用标志位控制执行 - 适用于高频事件处理
export function validateEmail(email: string): boolean {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(email);
}
邮箱验证函数: - 使用正则表达式验证 - 简单但实用的邮箱格式检查 - 返回布尔值
export function generateId(length: number = 8): string {
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
let result = '';
for (let i = 0; i < length; i++) {
result += chars.charAt(Math.floor(Math.random() * chars.length));
}
return result;
}
ID生成函数: - 生成指定长度的随机ID - 使用字母和数字组合 - 默认生成8位ID
export function sleep(ms: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, ms));
}
延迟函数: - 返回Promise,支持async/await - 用于测试或模拟异步操作 - 简洁的setTimeout封装
export function capitalize(str: string): string {
return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();
}
首字母大写函数: - 将字符串首字母转为大写 - 其余字母转为小写 - 常用于用户名格式化
export function truncateText(text: string, maxLength: number): string {
if (text.length <= maxLength) return text;
return text.slice(0, maxLength - 3) + '...';
}
文本截断函数: - 超出长度时添加省略号 - 保留指定长度的文本 - 用于UI中的文本截断显示
设计模式分析
1. 纯函数模式
- 所有函数都是纯函数,无副作用
- 相同输入始终产生相同输出
- 易于测试和调试
2. 泛型设计模式
- 使用TypeScript泛型保持类型安全
- 提供灵活的函数签名
- 编译时类型检查
3. 组合模式
cn函数组合了clsx和twMerge- 发挥各自优势,提供最佳体验
- 抽象复杂的组合逻辑
4. 工厂模式
debounce和throttle返回新函数- 根据参数创建定制化函数
- 闭包保持状态
性能优化
1. 类名合并优化
// 避免重复计算
const buttonClasses = cn(
'base-button-classes',
variant === 'primary' && 'primary-classes',
size === 'large' && 'large-classes'
);
2. 防抖节流应用
// 搜索输入防抖
const debouncedSearch = debounce((query: string) => {
performSearch(query);
}, 300);
// 滚动事件节流
const throttledScroll = throttle(() => {
updateScrollPosition();
}, 100);
使用示例
1. 类名合并
// 组件中使用
const Button = ({ variant, size, disabled, className, ...props }) => {
return (
<button
className={cn(
'px-4 py-2 rounded font-medium',
{
'bg-blue-500 text-white': variant === 'primary',
'bg-gray-200 text-gray-800': variant === 'secondary',
'opacity-50 cursor-not-allowed': disabled,
},
size === 'sm' && 'text-sm px-2 py-1',
size === 'lg' && 'text-lg px-6 py-3',
className
)}
{...props}
/>
);
};
2. 表单验证
// 表单验证示例
const validateForm = (formData: FormData) => {
const email = formData.get('email') as string;
const errors: string[] = [];
if (!validateEmail(email)) {
errors.push('请输入有效的邮箱地址');
}
return errors;
};
3. 数据格式化
// 显示格式化数据
const OrderSummary = ({ order }) => {
return (
<div>
<p>订单日期: {formatDate(order.createdAt)}</p>
<p>订单金额: {formatCurrency(order.amount)}</p>
<p>订单描述: {truncateText(order.description, 100)}</p>
</div>
);
};
扩展建议
1. 更多验证函数
export function validatePassword(password: string): {
isValid: boolean;
errors: string[];
} {
const errors: string[] = [];
if (password.length < 8) {
errors.push('密码至少需要8个字符');
}
if (!/[A-Z]/.test(password)) {
errors.push('密码需要包含大写字母');
}
if (!/[a-z]/.test(password)) {
errors.push('密码需要包含小写字母');
}
if (!/[0-9]/.test(password)) {
errors.push('密码需要包含数字');
}
return {
isValid: errors.length === 0,
errors
};
}
2. 更多格式化函数
export function formatFileSize(bytes: number): string {
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
if (bytes === 0) return '0 Bytes';
const i = Math.floor(Math.log(bytes) / Math.log(1024));
return Math.round(bytes / Math.pow(1024, i) * 100) / 100 + ' ' + sizes[i];
}
export function formatRelativeTime(date: Date): string {
const now = new Date();
const diffInSeconds = Math.floor((now.getTime() - date.getTime()) / 1000);
if (diffInSeconds < 60) return '刚刚';
if (diffInSeconds < 3600) return `${Math.floor(diffInSeconds / 60)}分钟前`;
if (diffInSeconds < 86400) return `${Math.floor(diffInSeconds / 3600)}小时前`;
return `${Math.floor(diffInSeconds / 86400)}天前`;
}
最佳实践
- 类型安全: 使用TypeScript类型定义
- 纯函数: 避免副作用,保持函数纯净
- 性能优化: 合理使用防抖和节流
- 错误处理: 提供完整的错误处理逻辑
- 文档注释: 为复杂函数提供JSDoc注释
- 单元测试: 为工具函数编写测试用例
这些工具函数构成了项目的基础设施,提供了类名处理、数据格式化、验证和性能优化等核心功能,为整个应用的开发提供了强有力的支持。
本文档为站内渲染。原始文件本地路径:saas/source/templates/模版-template-raphael-starterkit-v1-main-analysis-06-工具函数-util-c731a2.md(仅本地保留,不入库不部署)