
本文详解如何使用 angular 内置的 `keyvaluepipe` 遍历任意 json 对象(非数组),在 html 模板中以 `
在 Angular 中,*ngFor 默认仅支持可迭代对象(如数组),但 JSON 对象本身不可直接遍历。幸运的是,Angular 提供了内置管道 KeyValuePipe(自 v6.1 起可用),它能将对象自动转换为 {key: string, value: any}[] 形式的数组,从而完美适配 *ngFor。
✅ 正确的数据结构准备(TypeScript 层)
关键前提是:确保组件 TS 文件中定义的属性名与模板中引用的名称完全一致,且结构扁平化。避免多层嵌套导致路径错误。
根据你的 Handlebars 模板逻辑,应将数据简化为:
// 在组件类中(例如 email-preview.component.ts)
export class EmailPreviewComponent implements OnInit {
Previous: Record<string, any> = {};
Current: Record<string, any> = {};
ngOnInit() {
// 假设你已通过服务或输入获取到 formData
const formData = {
Message_Body: {
formChanges: {
Previous: { Events: 'TEST', AdditionalInfo: '' },
Current: { Events: 'TEST111', AdditionalInfo: 'test' }
}
}
};
this.Previous = formData.Message_Body.formChanges.Previous;
this.Current = formData.Message_Body.formChanges.Current;
}
}⚠️ 注意:原代码中 templateInput = { Message_Body: { Previous, Current } } 会导致模板需写成 Message_Body.Message_Body.Previous —— 这是常见错误根源。务必解构赋值为顶层属性(如 Previous / Current),提升可读性与健壮性。
✅ HTML 模板:用 | keyvalue 管道遍历对象
在 .html 文件中,直接使用 *ngFor + keyvalue 管道即可:
<div>
<h3>Title: This following has been changed!</h3>
<h3>Previous Values</h3>
<ul *ngIf="Previous && Object.keys(Previous).length > 0; else noPrev">
<li *ngFor="let item of Previous | keyvalue">
{{ item.key }}: {{ item.value === '' || item.value == null ? '(empty)' : item.value }}
</li>
</ul>
<ng-template #noPrev><p><em>No previous values.</em></p></ng-template>
<h3>Current Values</h3>
<ul *ngIf="Current && Object.keys(Current).length > 0; else noCurr">
<li *ngFor="let item of Current | keyvalue">
{{ item.key }}: {{ item.value === '' || item.value == null ? '(empty)' : item.value }}
</li>
</ul>
<ng-template #noCurr><p><em>No current values.</em></p></ng-template>
</div>✅ 效果输出:
Title: This following has been changed! Previous Values • Events: TEST • AdditionalInfo: (empty) Current Values • Events: TEST111 • AdditionalInfo: test
? 补充说明与最佳实践
-
keyvalue 管道默认按插入顺序排序(Angular ≥ 12),如需按字母序排列键,可传入比较函数:
<li *ngFor="let item of Previous | keyvalue: compareKeys">
compareKeys = (a: KeyValue<string, any>, b: KeyValue<string, any>) => a.key.localeCompare(b.key);
空值/undefined 安全处理:模板中使用 item.value === '' 显式判断空字符串(HTML 渲染时 {{ '' }} 会留白,建议统一提示为 (empty) 或 -)。
性能提示:keyvalue 管道在每次变更检测时会创建新数组。若对象极大(>100 键),建议在组件中预处理为数组并 OnPush 策略优化。
替代方案(不推荐):手动在 TS 中 Object.entries(obj) 转数组 → 更冗余,失去模板声明式优势;keyvalue 是 Angular 官方推荐的标准解法。
掌握 | keyvalue,你就能优雅、简洁、可维护地渲染任意结构化 JSON 数据——无论是配置项、表单快照,还是审计日志中的字段变更对比。










