angular变更检测和onPush策略
Posted litiyi
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了angular变更检测和onPush策略相关的知识,希望对你有一定的参考价值。
变更检测
更改任何模型时, Angular会检测到更改并立即更新视图。这是Angular中的更改检测。该机制的目的是确保基础视图始终与其对应的模型保持同步。
如 DOM事件(单击, 悬停等) AJAX请求 计时器(setTimer(), setInterval())
1 Angular默认的change detection一旦触发,它会重新计算模板中以及绑定的表达式,然后再执行相应的视图更新。Angular最佳实践提出不要在模板中做比较复杂的计算或函数。
2 用onpush进行性能提升,onPush机制那么就是告诉Angular在执行检测的时候,跳过当前组件内部的检测。只有当组件的input down输入有新值(变化)或内部有事件event up输出的时候,或者说组件再次通知Angular的检测机制来更新组件。
注意,在Angular的onPush检测机制中,只要组件的输入值input变化,组件内部才会执行更新。
但是在javascript中,有两个基本类型数据,一个是简单数据类型,比如\'abc\'、123、或者undefined这些都是简单数据类型;还有一个是对象数据类型。简单数据类型在作为参数的时候是按值传递的,而复杂数据类型是按引用传递的。
所以,如果按引用传递的值如Array或object数据类型发生变化,组件是不会更新的。
默认策略-更新引用类型时需要
this.arr = this.arr.push({xx:1})
onpush策略-组件再次通知Angular的检测机制来更新组件。
@Component({ selector: \'app-onpush\', changeDetection: ChangeDetectionStrategy.OnPush, }) export class OnpushComponent implements OnInit {
data = []; constructor(private cdr: ChangeDetectorRef) {} ngOnInit(): void {} private getDictList() {
this.data = this.data.push({id:2});
this.cdr.markForCheck();
}
Angular 性能优化实战
Angular 性能优化实战
Angular 是一个非常强大的前端框架,但是如果不注意性能优化,应用程序可能会变得非常慢并增加加载时间。 以下是一些Angular性能优化经验的实战建议:
1. 使用 OnPush 变更检测策略
默认情况下,Angular检查应用程序中发生的所有数据更改,从而导致性能下降。为了解决这个问题,可以使用OnPush变更检测策略,这将只在输入绑定值发生更改时才启动变更检测。这个策略只适用于具有@Input() properties的组件,并且需要手动设置。
import Component, ChangeDetectionStrategy from @angular/core;
@Component(
selector: app-sample-component,
templateUrl: ./sample.component.html,
styleUrls: [./sample.component.scss],
changeDetection: ChangeDetectionStrategy.OnPush
)
export class SampleComponent
// ...
定义一个组件并设置 changeDetection
选项为 OnPush
,如上所述。
2. 使用轻量级的管道
Angular中的管道可以用来转换数据,并在模板中显示不同的输出。使用轻量级的管道可以提高Angular应用的性能。
一个经典的例子是将日期格式化为特定的字符串形式。我们可以使用内置的DatePipe管道来实现这一点,但是它可能会导致性能问题。相反,我们可以编写一个自定义的轻量级管道来执行相同的任务:
import Pipe, PipeTransform from @angular/core;
@Pipe(
name: customDate
)
export class CustomDatePipe implements PipeTransform
transform(value: any): string
const date = new Date(value);
return `$date.getDate()/$date.getMonth() + 1/$date.getFullYear()`;
在模板中使用这个自定义管道:
<p> myDate | customDate </p>
在 Angular 中使用管道来转换数据是很方便的,但是需要注意的是,某些管道可能会对性能产生负面影响。建议遵循以下规则使用轻量级的管道:
- 尽可能使用纯管道: 纯管道指输入不变时,输出永远不变的管道,它们只在输入发生变化时进行计算,在模板中绑定的表达式将不会多次被执行。
- 避免使用复杂管道: 复杂管道需要更多的计算资源,因此应该尽可能避免使用它们。当您必须使用复杂管道时,应该将其结果缓存起来,以便在需要时可以重用它们。
import Pipe, PipeTransform from @angular/core;
@Pipe(name: uppercase)
export class UpperCasePipe implements PipeTransform
transform(value: string): string
return value.toUpperCase();
这样做的好处是这个自定义管道没有过多的附加操作或计算,因此它比内置的DatePipe稍微快一些,从而提高了整个应用程序的性能。
3. 使用懒加载模块
在 Angular 中,懒加载模块可以帮助你分割应用程序并提高加载时间。使用懒加载模块可以将某些代码推迟到用户需要时才加载。
为了使模块成为懒加载模块,你需要在路由中使用 loadChildren
而不是 component
属性。
const routes: Routes = [
path: lazy,
loadChildren: () => import(./lazy/lazy.module).then(m => m.LazyModule)
];
4. 使用 trackBy 帮助 ngFor 优化
当使用 ngFor 循环渲染数组或列表时,如果数据发生变化,“脏检查”机制会触发重新渲染所有列表项。
通过使用 trackBy
函数,可以告诉 Angular 如何跟踪列表项的变化,从而避免不必要的渲染。
<ul>
<li *ngFor="let item of items; trackBy: itemTrackByFn"> item </li>
</ul>
itemTrackByFn(index, item)
return item.id;
5. 避免在引用类型中改变对象的属性
在 Angular 应用程序中,通过在组件和服务之间传递引用类型,可以轻松地共享数据。
但是,如果你试图修改已经在其他地方使用的对象的属性,则所有对该对象的引用都将受到影响,这可能导致不必要的变更检测。
为了避免这种情况,尽量避免直接修改对象的属性,而是使用 Object.assign()
或 spread
运算符创建新对象。
const user = id: 1, name: John Doe, email: john@example.com ;
// 不好的写法
this.userService.updateUser(user.id, user.name);
user.email = new-email@example.com;
// 好的写法
this.userService.updateUser(user.id, user.name, email: new-email@example.com );
6. 使用虚拟滚动
当你需要处理大量数据时,虚拟滚动可以帮助你实现快速、流畅的滚动体验,而无需渲染整个列表。
Angular CDK 提供了一个名为 CdkVirtualScrollViewport
的指令,它可以帮助你实现虚拟滚动。
<cdk-virtual-scroll-viewport itemSize="50" class="example-viewport">
<div *cdkVirtualFor="let item of items" class="example-item">item</div>
</cdk-virtual-scroll-viewport>
以上是一些 Angular 性能优化的实战,其中一些技术可以单独应用,同时使用全部技巧可以帮助你最大程度地提高 Angular 应用程序的性能并改善用户体验。
7. 开启 AOT 编译
开启 AOT 编译可以大大提高应用程序的性能。AOT 编译将在构建期间对组件/指令和模板进行编译,并将生成的 JavaScript 代码直接注入到 HTML 模板中。这意味着在运行时,浏览器不再需要编译模板,从而减少启动时间和加载时间。
具体来说,以下是如何开启 AOT 编译:
- 在 Angular CLI 中使用
--aot
选项构建您的应用程序:ng build --aot
- 在 Angular 应用程序中配置 JIT 编译器,以便像 AOT 所做的那样提前编译组件:
@NgModule(
// ...
providers: [
provide: COMPILER_OPTIONS,
useValue:
providers: [useClass: JitCompiler]
,
multi: true
],
// ...
)
export class AppModule
以上是一些 Angular 性能优化的实战,其中一些技术可以单独应用,也可以同时使用,它可以帮助你最大程度地提高 Angular 应用程序的性能并改善用户体验。
以上是关于angular变更检测和onPush策略的主要内容,如果未能解决你的问题,请参考以下文章
Angular 5.0 变更检测策略 VS React 的变更检测策略
#私藏项目实操分享# Angular Change Detection 的学习笔记