角度变化检测策略:OnPush 和默认策略
已发表: 2021-06-18变更检测被称为检查当前状态和新状态的机制。 这两种状态之间的任何差异都表明存在需要更新的更改。 这意味着视图必须随着数据的变化而更新。
在应用程序更改期间组件中发生的任何更改都可以通过Angular 2+ 检测到。 每当模型发生变化时,相关的变化都会被 angular 检测到,并且视图会立即更新。 这种变化称为角度变化检测。
更改可能是从网络请求接收到的数据的结果,也可能是通过用户事件发生的。 随着应用程序大小的增加,必须通过更改检测方法执行更多工作。 角度检测对于在底层视图和相应模型之间保持同步是必要的。
角度模型的变化可能是由于以下任何原因:
- DOM 事件(单击、悬停等)
- AJAX 请求
- 计时器 (setTimer(), setInterval())
目录
先决条件
要掌握本文,您可能必须熟悉角度组件的概念。 此外,值类型和引用类型的概念可能有助于理解本文。
Angular中的变化检测
角度变化检测分两步完成,第一步是通过开发人员更新应用程序模型。 它可以通过发出事件或通过更改组件的属性来进行。 第二步,即角度反映模型的工作。 它检测是否有任何新数据显式推送到组件中。 这可以通过组件或使用异步管道订阅的 Observable 来完成。
因此,这两个步骤是:
- 更新应用模型(开发者);
- 在视图中反映模型的状态(Angular)。
角度变化检测检测常见浏览器事件的变化,如鼠标点击、HTTP 请求和其他类型的事件。 一旦检测到变化,就决定是否需要更新视图。
变更检测策略
存在两种角度变化检测策略,即默认策略和 onPush。
默认策略
- 模型上的更改由角度监控,以确保捕获模型中的所有更改。 通过角度检查新状态和先前状态之间的差异。
- 对于要更新的视图,角度应该可以访问新值,然后将其与旧值进行比较。 基于此决定是否更新视图。
- 因此,在默认策略中,角度围绕值是否有任何变化的问题。
- 没有关于组件依赖于何处的假设。 这是一种保守的策略,只要有相关的变化就会检查。 将对任何浏览器事件、时间、承诺和 XHR 执行检查。
- 当需要考虑包含许多组件的大型应用程序时,该策略可能会出现问题。
- 默认情况下,它使用ChangeDetectionStrategy.Default策略。
覆盖浏览器的默认机制
- 几个低级 API 将在启动时通过 Angular 进行修补。 这些 API 可能是addEventListener; 用于注册浏览事件的浏览器函数。
- addEventListener将被 angular 替换,新版本的性能与早期版本一样。
- addEventListener新版本向事件处理程序添加了更多功能。 通过 Angular 运行性能检查后更新 UI。
在职的
Zone.js 附带的库对浏览器 API 进行低级修补。
- zone被定义为多个JVM执行轮次下的执行内容。 通过这种机制,可以将额外的功能添加到浏览器中。 角度内部使用这些区域来检测任何变化并触发检测。
- 一个区域通常分为三个阶段,即开始稳定,区域内有任务运行不稳定,任务完成后稳定。
- 经过修补以支持更改检测的浏览器机制是:
- 浏览器事件,例如点击等。
- setInterval() 和 setTimeout()
- Ajax HTTP 请求
- 为了触发角度变化检测,Zone.js 用于修补另一个浏览器(如 Websockets)的几个 API。
- 此方法的一个限制是:如果 Zone.js 不支持浏览器 API,则在更改检测期间将不会触发。
触发变化检测时角度变化检测如何工作?
通过变化检测器检测触发的变化。 此更改检测器是在应用程序启动期间创建的。 可以考虑TodoItem组件的示例。 如果 todo 的状态被切换,组件将在接收到对象 Todo 时发出事件。 了解有关如何运行 Angular 项目的更多信息。
默认变更检测机制的工作
变更检测机制很简单。 在每个表达式中,将属性的当前值与表达式中先前状态的该属性的值进行比较。
- 属性值不同会将isChanged的值设置为 true 。
- OnPush 策略
- 在使用onPush策略时,角度不必对何时必须执行检查进行任何猜测。
- 根据输入参考的变化或组件本身触发的事件,角度将执行更改检查。
- 此外,可以明确要求 angular 执行更改检查。 这是通过 componentRef.markForCheck() 方法完成的。
- 此策略中的组件将仅取决于其输入。 只有在以下情况下才会执行变更检测策略:
- 输入参考发生了变化。
- 模型的组件或其任何子项中存在相关的更改。
- 当必须执行显式更改检测时。
- 当使用视图中的异步管道时。
- 与默认策略相比,onpush 策略主要围绕两个问题展开:
- 引用类型有什么变化吗?
- 如果引用类型的引用有变化,那么堆内存的值有变化吗?
- 它可以防止对组件和子组件进行不必要的检查。
为组件实现 onPush 策略
只有当一个新的引用作为@Input()值传递时,它才会触发更改检测。 这些值可以是基本类型,如数字、布尔值、字符串和 null。 也可以使用数组和对象。 修改后的对象或数组不能用于触发onPush 组件上的更改检测,因为不会为它们创建新引用。 因此,将传递一个新对象或数组引用来触发检测器检测变化。
为了避免更改检测方法中的错误,可以通过使用不可变对象和列表在任何地方使用onPush更改检测来构建应用程序。 可以通过创建新的对象引用来修改不可变对象,因此:
- 对于每次更改,都会触发onPush更改检测。
- 始终会创建一个新的对象引用,以防止出现错误。
在这种情况下,可以使用 Immutable.js,因为它包含对象 (Map) 和列表 (List) 的不可变数据结构。
- 在组件注解中添加changeDetection参数将实现 onPush 策略。 ChangeDetectorRef也可以用于完全控制,而不是每次都传递新的引用。
ChangeDetectorRef.detectChanges()
- 更改检测的方法可以通过changeDetectorRef中的分离和重新附加方法手动附加或分离。
ChangeDetectorRef.detach()和不可变的.js
当使用 onPush 策略进行变更检测时,如果强制执行不变性总是一个好主意。 在这种情况下,使用 Immutable.js。
immutable.js 是一个库,用于在 JavaScript 中结合不可变性以及 List、Stack 和 Map 等不可变数据结构。
要在项目中添加 Immutable.js,必须在终端中使用以下命令。 了解有关角度项目的更多信息。
$ npm install immutable –save
要从 Immutable.js 导入数据结构,必须使用以下命令。 在这种情况下,该命令显示仅导入 List 和 Map 数据结构。
从“不可变”导入 {Map, List} 也可以使用数组。
此外,如果使用 Immutable.js,也会有一些缺点。
- 使用 API 有点麻烦。
- 接口无法实现到数据模型,因为库 Imutable.js 不支持任何接口。
从世界顶级大学在线学习软件课程。 获得行政 PG 课程、高级证书课程或硕士课程,以加快您的职业生涯。
概括
本文向您介绍了变更检测的机制和策略。 默认情况下,Angular 将对所有组件执行更改检测。 此外,当数据发生突变时,可以应用 ChangeDetectorRef 来检测新引用中的更改。 对角开发的需求不断增加,这导致了印度的角开发人员工资。
如果你想了解更多关于软件技术、它的开发以及它背后的机制,你可以查看 upGrad 提供的软件开发中的执行 PG 程序 - 全栈开发专业化课程。 专业化课程是一个为期 23 周的在线课程,提供 300 多个案例研究,以提高您的知识和可用工具和编程语言,从而提高您的实践技能。 如果您对课程有任何疑问,请给我们留言。 我们的团队将与您联系。
Angular 中有哪些不同的变更检测策略?
Angular 提供了几种变更检测策略来优化变更检测的性能。 但是,默认策略名为检测。 在这个过程中,Angular 会遍历整个组件树,从根组件到子组件。 每次树发生变化时,Angular 都会通过调用它们的 _detectChanges 方法来通知组件。 对于使用 OnPush 变更检测策略的组件,Angular 不会每次都遍历整个树。 相反,它比较数据属性的当前值和以前的值,并仅在发生更改时调用 _detectChanges 方法。 默认情况下,Angular 使用遍历整个树的策略。
Angular 中的指令是什么?
Angular 中的指令是可重用的组件。 指令允许扩展 HTML 词汇并使其更具动态性。 这是 Angular 中引入的一个新概念,用于扩展用户界面。 指令是一种特殊类型的组件,可以用作属性、元素或类。 如果一个组件被用作元素,那么它被称为元素指令,如果它被用作属性,它被称为属性指令,如果它被用作类,它是一个类指令。 Angular 提供了大约 11 个内置指令,例如 ng-repeat、ng-show、ng-controller 等。Angular 还提供了创建自定义指令的工具。
Angularjs 中的过滤器是什么?
除了浏览器提供的过滤器之外,AngularJS 还提供了几个过滤器。 过滤器严格用于在向用户显示数据之前对其进行格式化。 始终建议使用过滤器过滤数据,以便用户每次都能看到相同的数据。 过滤器也可用于使数据验证更有效。 Angular.js 过滤器允许您获取一段 HTML 并根据您的意愿对其进行操作,例如大写、小写等。过滤器允许您获取一组值并根据这些值创建一个对象列表。