name: delon-util description: ‘@delon/util 技能 - 用于数组、字符串、日期、数字操作的实用函数库。适用于 ng-events 建筑工地进度跟踪系统。’
@delon/util - 实用函数库
触发模式:“utility”, “helper”, “@delon/util”, “format”, “deepCopy”, “deepMerge”
概述
@delon/util 为 ng-alain 应用程序中的常见数据操作任务提供了一套全面的实用函数集合。
包: @delon/util@20.1.0
分类
1. 数组实用工具 (array/)
deepCopy - 深度复制数组/对象
import { deepCopy } from '@delon/util/array';
const original = { name: '任务', items: [1, 2, 3], meta: { id: 1 } };
const copy = deepCopy(original);
// 对副本的更改不会影响原始对象
copy.items.push(4);
console.log(original.items); // [1, 2, 3]
console.log(copy.items); // [1, 2, 3, 4]
使用场景:
- 为不可变性克隆状态对象
- 在修改前创建独立副本
- 深度克隆表单数据
deepMerge - 深度合并对象
import { deepMerge } from '@delon/util/array';
const defaults = {
config: { theme: 'light', size: 'default' },
features: ['dashboard']
};
const custom = {
config: { theme: 'dark' },
features: ['reports']
};
const merged = deepMerge(defaults, custom);
// 结果: {
// config: { theme: 'dark', size: 'default' },
// features: ['dashboard', 'reports']
// }
其他数组函数
import {
groupBy, // 按属性分组数组
uniq, // 去重
uniqBy, // 按属性去重
orderBy // 按属性排序数组
} from '@delon/util/array';
// 按状态分组任务
const grouped = groupBy(tasks, 'status');
// { pending: [...], completed: [...] }
// 移除重复的ID
const uniqueIds = uniq([1, 2, 2, 3]); // [1, 2, 3]
// 按ID移除重复任务
const uniqueTasks = uniqBy(tasks, 'id');
// 排序任务
const sorted = orderBy(tasks, ['priority', 'createdAt'], ['asc', 'desc']);
2. 字符串实用工具 (string/)
format - 字符串格式化
import { format } from '@delon/util/string';
// 模板插值
const message = format('任务 {0} 已指派给 {1}', taskName, userName);
// 命名参数
const message2 = format('任务 {name} 的状态为 {status}', {
name: '地基施工',
status: '进行中'
});
其他字符串函数
import {
toCamelCase, // 转换为 camelCase
toPascalCase, // 转换为 PascalCase
toKebabCase, // 转换为 kebab-case
toSnakeCase, // 转换为 snake_case
truncate // 截断并添加省略号
} from '@delon/util/string';
toCamelCase('task-name'); // 'taskName'
toPascalCase('task-name'); // 'TaskName'
toKebabCase('TaskName'); // 'task-name'
toSnakeCase('TaskName'); // 'task_name'
truncate('Long text...', 10); // 'Long te...'
3. 日期实用工具 (date/)
getTimeDistance - 获取时间范围
import { getTimeDistance } from '@delon/util/date';
// 获取今天的日期范围
const today = getTimeDistance('today');
// [Date(2024-12-25 00:00:00), Date(2024-12-25 23:59:59)]
// 获取本周的日期范围
const week = getTimeDistance('week');
// 获取本月的日期范围
const month = getTimeDistance('month');
// 获取本年的日期范围
const year = getTimeDistance('year');
// 带偏移量的自定义范围
const lastWeek = getTimeDistance('week', -1);
支持的类型:
'today'- 当前天'week'- 当前周(周日至周六)'month'- 当前月'year'- 当前年- 自定义偏移量(负数为过去,正数为未来)
formatDistanceToNow - 相对时间
import { formatDistanceToNow } from '@delon/util/date';
const createdAt = new Date('2024-12-20');
const relative = formatDistanceToNow(createdAt);
// "5天前"
const futureDate = new Date('2024-12-30');
const future = formatDistanceToNow(futureDate);
// "5天后"
4. 数字实用工具 (number/)
currency - 货币格式化
import { currency } from '@delon/util/number';
// 格式化为货币
currency(1234567.89); // "$1,234,567.89"
currency(1234567.89, { unit: '¥' }); // "¥1,234,567.89"
currency(1234.5, { precision: 0 }); // "$1,235"
其他数字函数
import {
toFixed, // 四舍五入到固定小数位
toPercent, // 转换为百分比
toThousands // 添加千位分隔符
} from '@delon/util/number';
toFixed(1.2345, 2); // "1.23"
toPercent(0.1234); // "12.34%"
toPercent(0.1234, 1); // "12.3%"
toThousands(1234567); // "1,234,567"
5. 浏览器实用工具 (browser/)
copyToClipboard - 复制到剪贴板
import { copy } from '@delon/util/browser';
async copyTaskLink(taskId: string) {
const link = `${window.location.origin}/tasks/${taskId}`;
const success = await copy(link);
if (success) {
this.messageService.success('链接已复制');
} else {
this.messageService.error('复制失败');
}
}
其他浏览器函数
import {
scrollToTop, // 平滑滚动到顶部
deepGet, // 获取嵌套对象属性
deepSet, // 设置嵌套对象属性
isEmpty, // 检查值是否为空
isEqual, // 深度相等检查
updateHostClass // 更新宿主元素类
} from '@delon/util/browser';
scrollToTop();
scrollToTop({ duration: 500 });
const value = deepGet(obj, 'user.profile.name');
deepSet(obj, 'user.profile.name', 'New Name');
isEmpty(null); // true
isEmpty(''); // true
isEmpty([]); // true
isEmpty({}); // true
isEqual({ a: 1 }, { a: 1 }); // true
实际应用示例
任务管理实用工具
import { Component, signal, computed, inject } from '@angular/core';
import { deepCopy, groupBy, orderBy } from '@delon/util/array';
import { format } from '@delon/util/string';
import { getTimeDistance } from '@delon/util/date';
import { copy } from '@delon/util/browser';
import { NzMessageService } from 'ng-zorro-antd/message';
@Component({
selector: 'app-task-list',
standalone: true,
template: `
<nz-card>
<div nz-row [nzGutter]="16">
@for (group of groupedTasks() | keyvalue; track group.key) {
<div nz-col [nzSpan]="8">
<h3>{{ group.key }} ({{ group.value.length }})</h3>
@for (task of group.value; track task.id) {
<nz-card>
<h4>{{ task.title }}</h4>
<p>{{ formatTaskInfo(task) }}</p>
<button nz-button (click)="copyTaskLink(task.id)">
复制链接
</button>
</nz-card>
}
</div>
}
</div>
</nz-card>
`
})
export class TaskListComponent {
private messageService = inject(NzMessageService);
// 来自服务的原始任务
tasks = signal<Task[]>([]);
// 使用 @delon/util 按状态分组任务
groupedTasks = computed(() =>
groupBy(this.sortedTasks(), 'status')
);
// 按优先级和日期排序任务
sortedTasks = computed(() =>
orderBy(
this.tasks(),
['priority', 'createdAt'],
['asc', 'desc']
)
);
// 格式化任务信息
formatTaskInfo(task: Task): string {
return format(
'优先级: {priority}, 创建于 {date}',
{
priority: task.priority,
date: this.formatDate(task.createdAt)
}
);
}
// 复制任务链接到剪贴板
async copyTaskLink(taskId: string): Promise<void> {
const link = `${window.location.origin}/tasks/${taskId}`;
const success = await copy(link);
if (success) {
this.messageService.success('任务链接已复制');
} else {
this.messageService.error('复制失败,请手动复制');
}
}
// 克隆任务用于编辑
cloneTaskForEdit(task: Task): Task {
return deepCopy(task);
}
// 获取本周的任务
getThisWeekTasks(): Task[] {
const [start, end] = getTimeDistance('week');
return this.tasks().filter(t =>
t.createdAt >= start && t.createdAt <= end
);
}
private formatDate(date: Date): string {
return format(
'{year}-{month}-{day}',
{
year: date.getFullYear(),
month: String(date.getMonth() + 1).padStart(2, '0'),
day: String(date.getDate()).padStart(2, '0')
}
);
}
}
表单数据实用工具
import { Component, signal } from '@angular/core';
import { deepCopy, deepMerge } from '@delon/util/array';
import { isEmpty } from '@delon/util/browser';
@Component({
selector: 'app-task-form',
standalone: true,
template: `
<form nz-form (ngSubmit)="handleSubmit()">
<!-- 表单字段 -->
<button nz-button [disabled]="hasEmptyRequired()">
提交
</button>
</form>
`
})
export class TaskFormComponent {
// 默认表单值
private defaults = {
priority: 'medium',
status: 'pending',
assignee: null,
tags: []
};
// 带默认值的表单数据
formData = signal(deepCopy(this.defaults));
// 原始任务(用于编辑)
originalTask = signal<Task | null>(null);
// 加载任务进行编辑
loadTask(task: Task): void {
// 合并任务数据与默认值
const merged = deepMerge(this.defaults, task);
this.formData.set(merged);
this.originalTask.set(deepCopy(task));
}
// 检查必填字段是否为空
hasEmptyRequired(): boolean {
const data = this.formData();
return isEmpty(data.title) || isEmpty(data.assignee);
}
// 检查表单是否有更改
hasChanges(): boolean {
const original = this.originalTask();
if (!original) return true;
return !isEqual(original, this.formData());
}
handleSubmit(): void {
if (!this.hasEmptyRequired()) {
// 为提交创建干净副本
const submitData = deepCopy(this.formData());
// 提交...
}
}
}
最佳实践
1. 使用实用工具实现不可变性
✅ 应该这样做:
const taskCopy = deepCopy(task);
taskCopy.status = 'completed';
this.tasks.update(tasks => [...tasks, taskCopy]);
❌ 不应该这样做:
task.status = 'completed';
this.tasks.update(tasks => [...tasks, task]); // 修改了原始对象
2. 结合实用工具使用计算信号
✅ 应该这样做:
groupedTasks = computed(() => groupBy(this.tasks(), 'status'));
sortedTasks = computed(() => orderBy(this.tasks(), ['priority'], ['asc']));
3. 使用类型安全的实用工具
✅ 应该这样做:
import { deepCopy } from '@delon/util/array';
const copy: Task = deepCopy<Task>(originalTask);
性能考虑
- deepCopy: 对于大型对象开销较大 - 谨慎使用
- groupBy/orderBy: 包装在 computed() 中以避免重复计算
- getTimeDistance: 如果频繁使用,缓存结果
- copy: 异步操作 - 处理加载状态
集成检查清单
- [ ] 安装 @delon/util@20.1.0
- [ ] 导入特定实用工具(支持 tree-shaking)
- [ ] 与 Angular Signals 结合使用以实现响应性
- [ ] 添加 TypeScript 泛型以确保类型安全
- [ ] 处理异步操作(复制)
- [ ] 测试边界情况(null、undefined、空值)
交叉参考
- angular-component - 信号集成
- delon-form - 表单验证实用工具
- firebase-repository - 状态管理的 deepCopy
版本: 1.0
创建日期: 2025-12-25
维护者: ng-events(GigHub) 开发团队