多迈知识库
第二套高阶模板 · 更大气的阅读体验

ngIf 和 hidden 到底谁更省资源?Angular 里别乱用

发布时间:2026-01-25 10:21:11 阅读:86 次

刚接手一个老项目,首页加载慢得像在等泡面煮熟。打开 DevTools 一看,DOM 节点数破 2000,其中一大半是“明明看不见却还挂着”的元素——比如一个用户没登录时也渲染出来的个人中心弹窗,只是加了 [hidden]="!isLoggedIn"

hidden 是“藏起来”,不是“删掉”

hidden 属性本质就是 CSS 的 display: none。元素还在 DOM 里,绑定还在跑,事件监听器照常注册,子组件照样初始化、触发 ngOnInit、执行 ngOnChanges,甚至可能悄悄发请求。

举个例子:

<user-profile *ngIf="isLoggedIn"></user-profile>
<!-- vs -->
<user-profile [hidden]="!isLoggedIn"></user-profile>

前者:用户没登录时,user-profile 组件压根不创建,不走任何生命周期,内存里没它;

后者:不管登没登录,组件都创建了,模板渲染了,输入输出属性绑定了,change detection 还得每轮都扫它一遍。

ngIf 是“按需上岗”,有开销但更干净

*ngIf 会彻底销毁/重建视图。首次显示时多一次创建开销(实例化、渲染、绑定),但隐藏后内存释放、检测树变轻。适合切换频率低、内容较重的模块,比如后台管理页的「系统日志」Tab,平时根本不用,何必一直占着内存?

不过要注意:频繁切换(比如鼠标 hover 触发的下拉菜单)用 *ngIf 可能卡顿,因为反复创建销毁成本高。这时候 [hidden][style.display] 更合适——毕竟藏起来比重新招人再培训快。

实测小对比(Chrome Performance 面板)

在含 10 个 async 管道 + 表单控件的组件上:

  • [hidden] 切换 10 次:change detection 平均耗时 8.2ms/轮,内存占用稳定在 42MB;
  • *ngIf 切换 10 次:首次显示 15ms,后续平均 3.1ms/轮,内存峰值回落到 36MB;

差别不大?那试试把组件换成带 ngModelValidators.required 的 50 行表单——[hidden] 下 change detection 直接涨到 14ms,而 *ngIf 隐藏后这部分完全归零。

一句话选法

要彻底省资源、内容重、切换少 → 用 *ngIf
要快速显隐、内容轻、切换勤(如 Tooltip、折叠面板)→ 用 [hidden][class.hidden]

别再所有“暂时不用”都塞 [hidden] 了,有时候藏得越深,拖得越累。