6分钟阅读

角度变化检测和ONPUSH策略

艾哈迈德有五年多的Java体验。他领导了目标的内部AngularJS培训,并银河游戏官方首页了8k +下载的iOS应用程序。

您已开始使用Angular为您最喜爱的项目。你知道有哪些角提供,以及如何利用它 构建惊人的Web应用程序。但是,有一些关于角度的东西,并且知道它们可以让您更好地使用角度为您的项目。

数据流在几乎所有事物的中心 棱角,更改检测是值得了解的,因为它将帮助您更容易地追踪错误,并在使用复杂的数据集时提供进一步优化应用程序的机会。

角度变化检测和ONPUSH策略

在本文中,您将学习角度如何检测其数据结构的变化以及如何使其成为最不可变的,以使最大的角度变化的变化检测策略。

变形检测

当您更改任何型号时, Angular detects the changes and immediately updates the views. This is 改变检测 在角度。这种机制的目的是确保潜在的观点是 总是在同步 使用它们的相应模型。角度的这个核心特征是使框架蜱嘀嗒的原因,部分原因是有角度是一个整洁的选择 银河游戏官方首页现代Web应用程序.

由于以下任何一种情况,Angular的模型可以发生变化:

  • DOM事件(点击,悬停在等等)

  • Ajax请求

  • 定时器(SetTimer(),setInterval())

改变探测器

所有角度应用程序都由组件的分层树组成。在运行时,Angular为树中的每个组件创建一个单独的更改检测器类,然后,该组件最终形成类似于组件的层次结构树的更改检测器的层次结构。

每当触发更改检测时,Angular将沿着该变化探测器沿着该树木沿,以确定其中的任何一个是否报告了更改。

对于每个检测到的改变,始终执行变化检测周期一次,并从根部变化检测器开始,并以顺序方式一直下降。这种顺序设计选择很好,因为它以可预测的方式更新模型,因为我们知道组件数据只能来自其父。

更改探测器层次结构

更改检测器提供了一种方法来跟踪组件的先前和当前状态以及其结构,以便向角度报告变更。

如果Angular从更改检测器获取报告,则指示相应的组件再呈现并相应更新DOM。

改变检测策略

值与引用类型

为了了解改变检测策略是什么以及为什么它有效,我们必须先了解之间的差异 价值类型和参考类型 在JavaScript中。如果您已经熟悉了这作用,可以跳过本节。

要开始,让我们审查价值类型和参考类型及其分类。

价值类型

  • 布尔基

  • 空值

  • 不明确的

  • 数字

  • 细绳

为简单起见,可以想象这些类型只是将它们的值存储在堆栈内存(技术上不是真的,而是对于本文来说足够了)。例如,请参阅下面的图像中的堆栈内存及其值。

堆栈内存

参考类型

  • 阵列

  • 对象

  • 职能

这些类型有点复杂,因为它们存储了堆栈内存的引用,这指向它们在堆内存上的实际值。您可以看到堆栈内存和堆内存如何在下面的示例图像中一起工作。我们看到堆栈内存引用堆内存中引用类型的实际值。

堆栈内存和堆内存

在价值类型和参考类型之间进行的重要区别是,为了读取值类型的值,我们只需查询堆栈内存,而是为了读取引用类型的值,我们需要先查询堆栈内存以获取引用,然后使用该引用来查询堆内存以定位引用类型的值。

默认策略

正如我们之前所述的那样,角监测器在模型上发生变化,以确保它捕获所有变化。它将检查整个应用程序模型的先前状态和当前状态之间的任何差异。

棱角在默认更改检测策略中询问的问题是:模型中的任何值更改了吗?但是对于参考类型,我们可以实施策略,以便我们可以提出更好的问题。这是Onpush改变检测策略进入的地方。

onpush策略

ONPUSH策略背后的主要思想表明,如果我们将参考类型视为不可变量的对象,我们可以检测一个值是否更快地改变了。当参考类型是不可变的,这意味着每次更新时,堆栈内存的引用都必须更改。现在我们可以简单地检查:参考(在堆栈中)的参考类型已更改?如果是,则只需检查所有值(在堆上)。如果令人困惑,请参阅上一个堆栈堆图。

ONPush策略基本上提出了两个问题而不是一个问题。参考类型的参考改变了吗?如果是,则将堆内存中的值更改?

例如,假设我们有一个具有30个元素的不可变数组,我们想知道是否有任何更改。我们知道,为了对不可变阵列有任何更新,它必须改变它的参考(堆栈)。这意味着我们最初可以检查对数组的引用是否有任何不同,这可能会使我们从做30个检查(在堆中)来确定哪个元素是不同的。这被称为Onpush策略。

所以,你可能会问,将参考类型视为不变的参考类型是什么意思?这意味着我们永远不会设置引用类型的属性,而是将value重新分配在一起。见下文:

将物体视为可变的:

static mutable() {
  var before = {foo: "bar"};
  var current = before;
  current.foo = "hello";
  console.log(before === current);
  // => true
}

将物体视为不变:

static mutable() {
  var before = {foo: "bar"};
  var current = before;
  current = {foo "hello"};
  console.log(before === current);
  // => false
}

注意,在上面的示例中,我们“将”参考类型为“处理”的参考类型,因为惯例是不可变的,因此我们仍然使用可变物体,但只是“假装”他们是不可变的。

So how do you implement OnPush strategy for a component? All you need to do is add the changeDetection parameter in their @Component annotation.

import {ChangeDetectionStrategy, Component} from '@angular/core';

@Component({
  // ...
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class OnPushComponent {
  // ...
}

immutable.js.

如果一个决定在角分量上使用ONPUSH策略,这是一个好主意。这就是unmutable.js进来的地方。

immutable.js是Facebook创建的图书馆,用于JavaScript中的不可变形。它们有许多不可变数据结构,如列表,地图和堆栈。出于本文的目的,将说明列表和地图。有关更多参考,请查看官方文档 这里.

要为您的项目添加Immutable.js,请确保进入您的终端并运行:

$ npm install immutable --save

另请务必导入您正在使用的组件中的immutable.js中使用的数据结构。

import {Map, List} from 'immutable';

这就是如何使用immutable.js地图:

var foobar = {foo: "bar"};
var immutableFoobar = Map(foobar);

console.log(immutableFooter.get("foo"));
// => bar

并且,可以使用数组:

var helloWorld = ["Hello", "World!"];
var immutableHelloWorld = List(helloWorld);
console.log(immutableHelloWorld.first());
// => Hello
console.log(immutableHelloWorld.last());
// => World!

helloWorld.push("Hello Mars!");
console.log(immutableHelloWorld.last());
// => Hello Mars!

使用immutable.js的缺点

使用immutable.js有几个主要的可争解缺点。

正如您可能注意到的那样,使用它的API有点繁琐,传统的JavaScript银河游戏官方首页人员可能不喜欢这个。由于immutable.js不支持接口,因此无法实现更严重的问题,因为无法为数据模型实现数据模型的接口。

包起来

您可能会询问为什么Onpush策略不是Angular的默认策略。我认为它是因为角度不想强迫 javascript.银河游戏官方首页人员 使用不可变的物体。但是,这并不意味着你被禁止使用它。

如果这是您想要在下一个Web项目中杠杆的东西,您现在知道角度易于切换到不同的变化检测策略。

理解基础知识

什么是变化检测角度?

在Angular中,当您更改任何型号时,框架会检测到更改,并立即更新相关视图。这可确保底层视图始终同步。