Files
2026-07-13 21:37:07 +08:00

3.4 KiB
Raw Permalink Blame History

客户端工具函数

用于格式化、校验、转换和解析的纯函数。

快速参考

类别 示例
格式化函数 formatCurrencyformatDateformatBytes
校验函数 isValidEmailisValidUrlisValidPhone
转换函数 slugifytruncatecapitalize
解析函数 parseQueryparseJSONparseDate

规则

纯函数:

  • 相同输入 → 相同输出
  • 无副作用
  • 不改变外部状态
  • 无 API 调用,无 ref,无响应式

何时不应使用 utils

  • 有状态逻辑 → 使用 composables
  • Vue 特有逻辑 → 使用 composables
  • 组件逻辑 → 保留在组件内
  • API 调用 → 使用 queries

结构

// utils/formatters.ts
export function formatCurrency(amount: number, currency = 'USD'): string {
  return new Intl.NumberFormat('en-US', {
    style: 'currency',
    currency,
  }).format(amount)
}

export function formatRelativeTime(date: Date): string {
  const rtf = new Intl.RelativeTimeFormat('en', { numeric: 'auto' })
  const diff = date.getTime() - Date.now()
  const days = Math.floor(diff / (1000 * 60 * 60 * 24))
  return rtf.format(days, 'day')
}

命名: 描述性动词(formatCurrencyvalidateEmailparseQuery 组织: 按类别分组(formatters.tsvalidators.ts 导出: 仅使用具名导出

按类别举例

格式化函数:

// utils/formatters.ts
export function formatBytes(bytes: number): string { ... }
export function formatPhone(phone: string): string { ... }

校验函数:

// utils/validators.ts
export function isValidEmail(email: string): boolean {
  return /^[^\s@]+@[^\s@][^\s.@]*\.[^\s@]+$/.test(email)
}

export function isValidUrl(url: string): boolean {
  try { new URL(url); return true }
  catch { return false }
}

转换函数:

// utils/transformers.ts
export function slugify(text: string): string {
  return text.toLowerCase()
    .replace(/[^\w\s-]/g, '')
    .replace(/\s+/g, '-')
}

export function truncate(text: string, length: number): string {
  return text.length > length ? `${text.slice(0, length)}...` : text
}

解析函数:

// utils/parsers.ts
export function parseQuery(search: string): Record<string, string> {
  return Object.fromEntries(new URLSearchParams(search))
}

export function parseJSON<T>(json: string, fallback: T): T {
  try { return JSON.parse(json) }
  catch { return fallback }
}

常见错误

副作用(非纯函数):

// ❌ 错误 —— 改变了外部状态
let count = 0
export function increment() {
  count++
  return count
}

// ✅ 正确 —— 纯函数
export function add(a: number, b: number): number {
  return a + b
}

将有状态逻辑用于 utils

// ❌ 错误 —— 应使用 composable
export function useCounter() { ... }

// ✅ 正确 —— 纯转换函数
export function formatCount(count: number): string { ... }

组织结构

小型项目使用扁平结构:

utils/
├── formatters.ts
├── validators.ts
└── transformers.ts

大型项目使用嵌套结构:

utils/
├── formatters/
│   ├── date.ts
│   ├── currency.ts
│   └── index.ts
└── validators/
    ├── email.ts
    └── index.ts