Angular 4应用大量警告致性能下降,求助解决方案(使用Angular Material)
我之前也踩过Angular 4 + Angular Material的性能坑,尤其是控制台堆了一堆冗余调用和警告的情况,给你整理几个针对性的排查和解决方向,应该能帮到你:
1. 先定位冗余警告与过量函数调用的根源
- 检查Angular Material版本兼容性:Angular 4对应的Material稳定版本是
2.x系列(比如@angular/material@2.0.0-beta.12),如果你误用了更高版本的Material,大概率会出现不兼容的冗余警告和额外函数调用。可以通过npm list @angular/material命令查看当前版本,确保和Angular 4的版本完全匹配。 - 启用OnPush变更检测策略:Angular默认的变更检测会频繁扫描组件树,Material组件的交互(比如表单输入、弹窗切换)很容易触发不必要的检测。给频繁更新的组件手动设置
ChangeDetectionStrategy.OnPush,能大幅减少无效的函数调用:
import { Component, ChangeDetectionStrategy } from '@angular/core'; @Component({ selector: 'app-target-component', templateUrl: './target-component.component.html', changeDetection: ChangeDetectionStrategy.OnPush }) export class TargetComponentComponent { }
- 清理RxJS订阅泄漏:控制台的大量重复函数调用,很多时候来自未取消的订阅(比如MatDialog的关闭事件、MatSelect的选项变更订阅)。一定要在组件销毁时取消所有订阅,推荐用
takeUntil操作符统一管理:
import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; import { MatDialog } from '@angular/material'; export class TargetComponentComponent implements OnDestroy { private destroy$ = new Subject<void>(); constructor(private dialog: MatDialog) {} ngOnInit() { this.dialog.open(YourDialogComponent) .afterClosed() .pipe(takeUntil(this.destroy$)) .subscribe(result => { /* 你的业务逻辑 */ }); } ngOnDestroy() { this.destroy$.next(); this.destroy$.complete(); } }
2. 关于EventEmitter passive:true无效的补充说明
Angular的EventEmitter本身并不支持passive选项,你可能混淆了原生DOM事件的配置。如果是Material组件的滚动、触摸等原生事件导致的性能问题,需要手动给原生事件绑定添加passive参数:
- 模板中直接绑定的写法:
<div (touchstart)="onTouchStart($event, { passive: true })"></div>
- 通过Renderer2手动添加事件监听的写法:
import { Renderer2, ElementRef } from '@angular/core'; constructor(private renderer: Renderer2, private el: ElementRef) {} ngOnInit() { // 给组件根元素添加被动滚动监听 this.renderer.listen(this.el.nativeElement, 'scroll', () => { /* 你的滚动逻辑 */ }, { passive: true }); }
3. 处理控制台冗余警告
- 替换过时API:如果警告是Material组件的过时API提示(比如旧版的
Md前缀组件,现在统一用Mat前缀),直接替换成当前版本的API就能消除警告,同时避免潜在的性能损耗。 - 生产环境过滤非关键警告:如果是无法避免的组件内部警告,可以在生产环境中针对性过滤。在
main.ts中添加如下代码:
import { enableProdMode } from '@angular/core'; import { environment } from './environments/environment'; if (environment.production) { enableProdMode(); // 过滤特定警告(比如匹配包含"deprecated"的警告) const originalWarn = console.warn; console.warn = (...args) => { if (!args[0]?.includes('deprecated')) { originalWarn.apply(console, args); } }; }
4. 用性能工具精准定位瓶颈
打开Chrome DevTools的Performance面板,录制你操作应用的全过程,重点关注:
- 频繁触发的变更检测周期(标记为
Angular Change Detection的任务) - Material组件的渲染耗时(比如
Render阶段的长任务) - 重复执行的事件回调或订阅逻辑
通过工具定位到具体的耗时点,再针对性优化会更高效。
内容的提问来源于stack exchange,提问作者ImRan ALi ShAh
相关产品推荐
相关产品推荐

