isChanged
sera défini sur true, c'est tout ! En gros, il compare les valeurs à l'aide d'une méthode appelée looseNotIdentical()
. 🎜🎜Qu'en est-il de l'objet imbriqué propriétaire
? 🎜🎜🎜Nous pouvons voir dans le code du détecteur de changement que la propriété owner
de l'objet imbriqué est également vérifiée pour détecter les différences. Mais seul l'attribut firstname
est comparé, pas l'attribut lastname
. En effet, lastname
n'est pas utilisé dans le composant template
! De même, l'attribut id de niveau supérieur de Todo n'est pas comparé pour la même raison. 🎜🎜Avec cela, nous pouvons dire en toute sécurité : 🎜默认情况下,Angular Change Detection 通过检查模板表达式的值是否已更改来工作。
默认情况下,Angular Change Detection 通过检查模板表达式的值是否已更改来工作。
我们还可以得出结论:
默认情况下,Angular 不做深度对象比较来检测变化,它只考虑模板使用的属性
为什么默认情况下更改检测会这样工作?" >🎜À quoi ressemble un détecteur de changement ? 🎜🎜🎜Nous pouvons réellement voir à quoi ressemble le détecteur de changement au moment de l'exécution ! Pour le voir, ajoutez simplement du code dans la classe Todo pour déclencher un point d'arrêt lors de l'accès à une certaine propriété. 🎜🎜Lorsque le point d'arrêt est atteint, nous pouvons parcourir la trace de la pile et voir la détection des modifications : 🎜🎜
🎜🎜Cette méthode peut paraître étrange au début, avec toutes les variables portant des noms étranges. Mais en creusant plus profondément, nous avons remarqué qu'il faisait quelque chose de très simple : pour chaque expression utilisée dans le modèle, il compare la valeur actuelle de la propriété utilisée dans l'expression à la valeur précédente de cette propriété. 🎜🎜Si les valeurs de propriété avant et après sont différentes, isChanged
sera défini sur true, c'est tout ! En gros, il compare les valeurs à l'aide d'une méthode appelée looseNotIdentical()
. 🎜🎜Qu'en est-il de l'objet imbriqué propriétaire
? 🎜🎜🎜Nous pouvons voir dans le code du détecteur de changement que la propriété owner
de l'objet imbriqué est également vérifiée pour détecter les différences. Mais seul l'attribut firstname
est comparé, pas l'attribut lastname
. En effet, lastname
n'est pas utilisé dans le composant template
! De même, l'attribut id de niveau supérieur de Todo n'est pas comparé pour la même raison. 🎜🎜Avec cela, nous pouvons dire en toute sécurité : 🎜默认情况下,Angular Change Detection 通过检查模板表达式的值是否已更改来工作。
propriétaire
? 🎜🎜🎜Nous pouvons voir dans le code du détecteur de changement que la propriété owner
de l'objet imbriqué est également vérifiée pour détecter les différences. Mais seul l'attribut firstname
est comparé, pas l'attribut lastname
. En effet, lastname
n'est pas utilisé dans le composant template
! De même, l'attribut id de niveau supérieur de Todo n'est pas comparé pour la même raison. 🎜🎜Avec cela, nous pouvons dire en toute sécurité : 🎜默认情况下,Angular Change Detection 通过检查模板表达式的值是否已更改来工作。
我们还可以得出结论:
默认情况下,Angular 不做深度对象比较来检测变化,它只考虑模板使用的属性
为什么默认情况下更改检测会这样工作?



Une brève analyse du mécanisme de détection de changement dans Angular
Qu'est-ce que la détection de changement ?
Dans le processus de développement d'applications, l'état représente les données qui doivent être affichées sur l'application. Lorsque l'état change, un mécanisme est souvent nécessaire pour détecter le changement d'état et mettre à jour l'interface correspondante en conséquence. Ce mécanisme est appelé mécanisme de détection des changements. [Recommandations du didacticiel associé : "Tutoriel angulaire"]
Dans le développement WEB, la mise à jour de l'interface de l'application revient en fait à modifier l'arborescence DOM. Étant donné que les opérations DOM sont coûteuses, une détection des changements inefficace entraînera de mauvaises performances des applications. Par conséquent, l’efficacité du cadre dans la mise en œuvre du mécanisme de détection des changements détermine en grande partie ses performances.
Comment la détection des changements est implémentée
Angular peut détecter lorsque les données des composants changent, puis restituer automatiquement la vue pour refléter ce changement. Mais comment peut-il faire cela après un événement de bas niveau comme un clic sur un bouton ?
À travers Zone, Angular peut déclencher automatiquement le mécanisme de détection de changement.
Qu'est-ce que Zone ? En bref, Zone est un contexte d'exécution, qui peut être compris comme un environnement d'exécution. Différentes des environnements d'exécution de navigateur courants, toutes les tâches asynchrones exécutées dans ce lien sont appelées Tâches. Zone fournit un ensemble de hooks pour ces tâches, permettant aux développeurs de « surveiller » facilement toutes les tâches asynchrones.
Hors sujet : Puisque Angular préconise fortement l'utilisation d'objets Observable (Observable), si vous développez une application entièrement basée sur Observable, vous pouvez remplacer Zone pour implémenter la fonction de suivi de la pile d'appels, et les performances seront légèrement mieux que d'utiliser Zone.
// Angular 在 v5.0.0-beta.8 起可以通过配置不使用 Zone import { platformBrowser } from '@angular/platform-browser'; platformBrowser().bootstrapModuleFactory(AppModuleNgFactory, { ngZone: 'noop' });
Remplacer le mécanisme par défaut du navigateur
Angular réécrira l'API de bas niveau du navigateur au démarrage, comme addEventListener
, qui est une fonction du navigateur utilisée pour enregistrer tous les événements du navigateur, y compris les clics. manutention. Angular remplacera addEventListener
par un nouvel équivalent à ceci : addEventListener
,它是用于注册所有浏览器事件的浏览器函数,包括点击处理。Angular 将替换addEventListener
为与此等效的新版本:
// this is the new version of addEventListener function addEventListener(eventName, callback) { // call the real addEventListener callRealAddEventListener(eventName, function() { //first call the original callback callback(...); // and then run Angular-specific functionality var changed = angular.runChangeDetection(); if (changed) { angular.reRenderUIPart(); } }); }
新的addEventListener
为任何事件处理程序添加了更多功能:不仅调用了注册的回调,而且 Angular 有机会运行更改检测并更新 UI。
支持浏览器异步 API
修补了以下常用浏览器机制以支持更改检测:
- 所有浏览器事件(单击、鼠标悬停、按键等)
setTimeout()
和setInterval()
- Ajax HTTP 请求
事实上,Zone.js 修补了许多其他浏览器 API,以透明地触发 Angular 更改检测,例如 Websockets。
这种机制的一个限制是,如果由于某种原因 Zone.js 不支持的异步浏览器 API,则不会触发更改检测。例如,IndexedDB 回调就是这种情况。
默认的变更检测机制是如何工作的?
每个 Angular 组件都有一个关联的变更检测器,它是在应用程序启动时创建的。例如:
@Component({ selector: 'todo-item', template: `<span class="todo noselect" (click)="onToggle()">{{todo.owner.firstname}} - {{todo.description}} - completed: {{todo.completed}}</span>` }) export class TodoItem { @Input() todo:Todo; @Output() toggle = new EventEmitter<Object>(); onToggle() { this.toggle.emit(this.todo); } }
该组件将接收一个 Todo 对象作为输入,并在 todo 状态被切换时发出一个事件。
export class Todo { constructor(public id: number, public description: string, public completed: boolean, public owner: Owner) { } }
我们可以看到 Todo 有一个属性owner
,它本身就是一个具有两个属性的对象:firstname
和lastname
。
变更检测器是什么样的?
我们实际上可以在运行时看到变化检测器的样子!要查看它,只需在 Todo 类中添加一些代码以在访问某个属性时触发断点。
当断点命中时,我们可以遍历堆栈跟踪并查看变化检测:
这个方法一开始可能看起来很奇怪,所有变量都奇怪命名。但是通过深入研究,我们注意到它在做一些非常简单的事情:对于模板中使用的每个表达式,它会将表达式中使用的属性的当前值与该属性的先前值进行比较。
如果前后的属性值不同,就会设置isChanged
为true,就这样!差不多,它是通过使用一个名为looseNotIdentical()
的方法来比较值。
那么嵌套对象owner
呢?
我们可以在更改检测器代码中看到 owner
嵌套对象的属性也正在检查差异。但只比较 firstname
属性,而不是 lastname
属性。这是因为组件template
中没有使用lastname
@Component({ selector: 'todo-list', changeDetection: ChangeDetectionStrategy.OnPush, template: ... }) export class TodoList { ... }
addEventListener
ajoute plus de fonctionnalités à tout gestionnaire d'événements : non seulement les rappels enregistrés sont appelés, et Angular a un chance d’exécuter la détection des modifications et de mettre à jour l’interface utilisateur. Prise en charge de l'API asynchrone du navigateur🎜🎜🎜Correction des mécanismes courants du navigateur suivants pour prendre en charge la détection des modifications : 🎜- Tous les événements du navigateur (clic, survol de la souris, touche appuyez, etc.)
setTimeout()
et setInterval()
- Requête HTTP Ajax
ul >🎜En fait, Zone.js corrige de nombreuses autres API de navigateur pour déclencher de manière transparente la détection des changements angulaires, telles que les Websockets. 🎜🎜Une limitation de ce mécanisme est que si, pour une raison quelconque, Zone.js ne prend pas en charge l'API du navigateur asynchrone, la détection des modifications ne sera pas déclenchée. C'est le cas des rappels IndexedDB par exemple. 🎜🎜Comment fonctionne le mécanisme de détection des modifications par défaut ? 🎜🎜🎜Chaque composant angulaire est associé à un détecteur de changement, qui est créé au démarrage de l'application. Par exemple : 🎜@Component({
selector: 'app',
template: `<div>
<todo-list [todos]="todos"></todo-list>
</div>
<button (click)="toggleFirst()">Toggle First Item</button>
<button (click)="addTodo()">Add Todo to List</button>`
})
export class App {
todos:Array = initialData;
constructor() {
}
toggleFirst() {
this.todos[0].completed = ! this.todos[0].completed;
}
addTodo() {
let newTodos = this.todos.slice(0);
newTodos.push( new Todo(1, "TODO 4",
false, new Owner("John", "Doe")));
this.todos = newTodos;
}
}
Copier après la connexionCopier après la connexion🎜Ce composant recevra un objet Todo en entrée et émettra un événement lorsque l'état todo est basculé. 🎜ngAfterViewChecked() {
if (this.callback && this.clicked) {
console.log("changing status ...");
this.callback(Math.random());
}
}
Copier après la connexionCopier après la connexion🎜On voit que Todo a un attribut owner
, qui lui-même est un objet avec deux attributs : firstname
et lastname
. 🎜🎜À quoi ressemble un détecteur de changement ? 🎜🎜🎜Nous pouvons réellement voir à quoi ressemble le détecteur de changement au moment de l'exécution ! Pour le voir, ajoutez simplement du code dans la classe Todo pour déclencher un point d'arrêt lors de l'accès à une certaine propriété. 🎜🎜Lorsque le point d'arrêt est atteint, nous pouvons parcourir la trace de la pile et voir la détection des modifications : 🎜🎜
🎜🎜Cette méthode peut paraître étrange au début, avec toutes les variables portant des noms étranges. Mais en creusant plus profondément, nous avons remarqué qu'il faisait quelque chose de très simple : pour chaque expression utilisée dans le modèle, il compare la valeur actuelle de la propriété utilisée dans l'expression à la valeur précédente de cette propriété. 🎜🎜Si les valeurs de propriété avant et après sont différentes, isChanged
sera défini sur true, c'est tout ! En gros, il compare les valeurs à l'aide d'une méthode appelée looseNotIdentical()
. 🎜🎜Qu'en est-il de l'objet imbriqué propriétaire
? 🎜🎜🎜Nous pouvons voir dans le code du détecteur de changement que la propriété owner
de l'objet imbriqué est également vérifiée pour détecter les différences. Mais seul l'attribut firstname
est comparé, pas l'attribut lastname
. En effet, lastname
n'est pas utilisé dans le composant template
! De même, l'attribut id de niveau supérieur de Todo n'est pas comparé pour la même raison. 🎜🎜Avec cela, nous pouvons dire en toute sécurité : 🎜默认情况下,Angular Change Detection 通过检查模板表达式的值是否已更改来工作。
我们还可以得出结论:
默认情况下,Angular 不做深度对象比较来检测变化,它只考虑模板使用的属性
为什么默认情况下更改检测会这样工作?
Angular 的主要目标之一是更加透明和易于使用,因此框架用户不必费尽心思调试框架并了解内部机制即可有效地使用它。
如果 Angular 默认更改检测机制基于组件输入的参考比较而不是默认机制,那会是什么情况?即使是像 TODO 应用程序这样简单的东西也很难构建:开发人员必须非常小心地创建一个新的 Todo,而不是简单地更新属性。
OnPush
变化检测策略
如果你觉得默认模式影响了性能,我们也可以自定义 Angular 更改检测。将组件更改检测策略更新为OnPush
:
@Component({
selector: 'todo-list',
changeDetection: ChangeDetectionStrategy.OnPush,
template: ...
})
export class TodoList {
...
}
Copier après la connexionCopier après la connexion现在让我们在应用程序中添加几个按钮:一个是通过直接改变列表的第一项来切换列表的第一项,另一个是向整个列表添加一个 Todo。代码如下所示:
@Component({
selector: 'app',
template: `<div>
<todo-list [todos]="todos"></todo-list>
</div>
<button (click)="toggleFirst()">Toggle First Item</button>
<button (click)="addTodo()">Add Todo to List</button>`
})
export class App {
todos:Array = initialData;
constructor() {
}
toggleFirst() {
this.todos[0].completed = ! this.todos[0].completed;
}
addTodo() {
let newTodos = this.todos.slice(0);
newTodos.push( new Todo(1, "TODO 4",
false, new Owner("John", "Doe")));
this.todos = newTodos;
}
}
Copier après la connexionCopier après la connexion现在让我们看看这两个新按钮的行为:
- 第一个按钮“切换第一项”不起作用!这是因为该
toggleFirst()
方法直接改变了列表中的一个元素。
TodoList
无法检测到这一点,因为它的输入参考todos
没有改变 - 第二个按钮确实有效!请注意,该方法
addTodo()
创建了 todo 列表的副本,然后将项目添加到副本中,最后将 todos 成员变量替换为复制的列表。这会触发更改检测,因为组件检测到其输入中的参考更改:它收到了一个新列表! - 在第二个按钮中,直接改变 todos 列表是行不通的!我们真的需要一个新的清单。
OnPush
只是通过引用比较输入吗?
情况并非如此。当使用 OnPush 检测器时,框架将在 OnPush 组件的任何输入属性更改、触发事件或 Observable 触发事件时检查
尽管允许更好的性能,但OnPush
如果与可变对象一起使用,则使用会带来很高的复杂性成本。它可能会引入难以推理和重现的错误。但是有一种方法可以使使用OnPush
可行。
使用 Immutable.js 简化 Angular 应用程序的构建
如果我们只使用不可变对象和不可变列表来构建我们的应用程序,则可以OnPush
透明地在任何地方使用,而不会遇到更改检测错误的风险。这是因为对于不可变对象,修改数据的唯一方法是创建一个新的不可变对象并替换之前的对象。使用不可变对象,我们可以保证:
- 新的不可变对象将始终触发
OnPush
更改检测 - 我们不会因为忘记创建对象的新副本而意外创建错误,因为修改数据的唯一方法是创建新对象
实现不可变的一个不错的选择是使用Immutable.js库。该库为构建应用程序提供了不可变原语,例如不可变对象(映射)和不可变列表。
避免变更检测循环:生产与开发模式
Angular 更改检测的重要属性之一是,与 AngularJs 不同,它强制执行单向数据流:当我们的控制器类上的数据更新时,更改检测运行并更新视图。
如何在 Angular 中触发变更检测循环?
一种方法是如果我们使用生命周期回调。例如,在TodoList组件中,我们可以触发对另一个组件的回调来更改其中一个绑定:
ngAfterViewChecked() {
if (this.callback && this.clicked) {
console.log("changing status ...");
this.callback(Math.random());
}
}
Copier après la connexionCopier après la connexion控制台中将显示一条错误消息:
EXCEPTION: Expression '{{message}} in App@3:20' has changed after it was checked
Copier après la connexion仅当我们在开发模式下运行 Angular 时才会抛出此错误消息。如果我们启用生产模式会发生什么?
在生产模式下,错误不会被抛出,问题也不会被发现。
在开发阶段始终使用开发模式会更好,因为这样可以避免问题。这种保证是以 Angular 总是运行两次变更检测为代价的,第二次检测这种情况。在生产模式下,变更检测只运行一次。
打开/关闭变化检测,并手动触发它
在某些特殊情况下,我们确实想要关闭更改检测。想象一下这样一种情况,大量数据通过 websocket 从后端到达。我们可能只想每 5 秒更新一次 UI 的某个部分。为此,我们首先将更改检测器注入到组件中:
constructor(private ref: ChangeDetectorRef) {
ref.detach();
setInterval(() => {
this.ref.detectChanges();
}, 5000);
}
Copier après la connexion正如我们所看到的,我们只是分离了变化检测器,这有效地关闭了变化检测。然后我们只需每 5 秒通过调用手动触发它detectChanges()
。
现在让我们快速总结一下我们需要了解的关于 Angular 变更检测的所有内容:它是什么,它是如何工作的以及可用的主要变更检测类型是什么。
概括
Angular 更改检测是一个内置的框架功能,可确保组件数据与其 HTML 模板视图之间的自动同步。
更改检测的工作原理是检测常见的浏览器事件,如鼠标点击、HTTP 请求和其他类型的事件,并确定每个组件的视图是否需要更新。
变更检测有两种类型:
- 默认更改检测:Angular 通过比较事件发生前后的所有模板表达式值来决定是否需要更新视图,用于组件树的所有组件
- OnPush 更改检测:这通过检测是否已通过组件输入或使用异步管道订阅的 Observable 将某些新数据显式推送到组件中来工作
Angular默认更改检测机制实际上与 AngularJs 非常相似:它比较浏览器事件之前和之后模板表达式的值,以查看是否有更改。它对所有组件都这样做。但也有一些重要的区别:
一方面,没有变化检测循环,也没有 AngularJs 中命名的摘要循环。这允许仅通过查看其模板和控制器来推理每个组件。
另一个区别是,由于变化检测器的构建方式,检测组件变化的机制要快得多。
最后,与 AngularJs 不同的是,变化检测机制是可定制的。
更多编程相关知识,请访问:编程教学!!
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!
setTimeout()
et setInterval()
🎜Comment fonctionne le mécanisme de détection des modifications par défaut ? 🎜🎜🎜Chaque composant angulaire est associé à un détecteur de changement, qui est créé au démarrage de l'application. Par exemple : 🎜@Component({
selector: 'app',
template: `<div>
<todo-list [todos]="todos"></todo-list>
</div>
<button (click)="toggleFirst()">Toggle First Item</button>
<button (click)="addTodo()">Add Todo to List</button>`
})
export class App {
todos:Array = initialData;
constructor() {
}
toggleFirst() {
this.todos[0].completed = ! this.todos[0].completed;
}
addTodo() {
let newTodos = this.todos.slice(0);
newTodos.push( new Todo(1, "TODO 4",
false, new Owner("John", "Doe")));
this.todos = newTodos;
}
}
Copier après la connexionCopier après la connexion🎜Ce composant recevra un objet Todo en entrée et émettra un événement lorsque l'état todo est basculé. 🎜ngAfterViewChecked() {
if (this.callback && this.clicked) {
console.log("changing status ...");
this.callback(Math.random());
}
}
Copier après la connexionCopier après la connexion🎜On voit que Todo a un attribut owner
, qui lui-même est un objet avec deux attributs : firstname
et lastname
. 🎜🎜À quoi ressemble un détecteur de changement ? 🎜🎜🎜Nous pouvons réellement voir à quoi ressemble le détecteur de changement au moment de l'exécution ! Pour le voir, ajoutez simplement du code dans la classe Todo pour déclencher un point d'arrêt lors de l'accès à une certaine propriété. 🎜🎜Lorsque le point d'arrêt est atteint, nous pouvons parcourir la trace de la pile et voir la détection des modifications : 🎜🎜
🎜🎜Cette méthode peut paraître étrange au début, avec toutes les variables portant des noms étranges. Mais en creusant plus profondément, nous avons remarqué qu'il faisait quelque chose de très simple : pour chaque expression utilisée dans le modèle, il compare la valeur actuelle de la propriété utilisée dans l'expression à la valeur précédente de cette propriété. 🎜🎜Si les valeurs de propriété avant et après sont différentes, isChanged
sera défini sur true, c'est tout ! En gros, il compare les valeurs à l'aide d'une méthode appelée looseNotIdentical()
. 🎜🎜Qu'en est-il de l'objet imbriqué propriétaire
? 🎜🎜🎜Nous pouvons voir dans le code du détecteur de changement que la propriété owner
de l'objet imbriqué est également vérifiée pour détecter les différences. Mais seul l'attribut firstname
est comparé, pas l'attribut lastname
. En effet, lastname
n'est pas utilisé dans le composant template
! De même, l'attribut id de niveau supérieur de Todo n'est pas comparé pour la même raison. 🎜🎜Avec cela, nous pouvons dire en toute sécurité : 🎜默认情况下,Angular Change Detection 通过检查模板表达式的值是否已更改来工作。
@Component({ selector: 'app', template: `<div> <todo-list [todos]="todos"></todo-list> </div> <button (click)="toggleFirst()">Toggle First Item</button> <button (click)="addTodo()">Add Todo to List</button>` }) export class App { todos:Array = initialData; constructor() { } toggleFirst() { this.todos[0].completed = ! this.todos[0].completed; } addTodo() { let newTodos = this.todos.slice(0); newTodos.push( new Todo(1, "TODO 4", false, new Owner("John", "Doe"))); this.todos = newTodos; } }
ngAfterViewChecked() { if (this.callback && this.clicked) { console.log("changing status ..."); this.callback(Math.random()); } }

isChanged
sera défini sur true, c'est tout ! En gros, il compare les valeurs à l'aide d'une méthode appelée looseNotIdentical()
. 🎜🎜Qu'en est-il de l'objet imbriqué propriétaire
? 🎜🎜🎜Nous pouvons voir dans le code du détecteur de changement que la propriété owner
de l'objet imbriqué est également vérifiée pour détecter les différences. Mais seul l'attribut firstname
est comparé, pas l'attribut lastname
. En effet, lastname
n'est pas utilisé dans le composant template
! De même, l'attribut id de niveau supérieur de Todo n'est pas comparé pour la même raison. 🎜🎜Avec cela, nous pouvons dire en toute sécurité : 🎜默认情况下,Angular Change Detection 通过检查模板表达式的值是否已更改来工作。
默认情况下,Angular Change Detection 通过检查模板表达式的值是否已更改来工作。
我们还可以得出结论:
默认情况下,Angular 不做深度对象比较来检测变化,它只考虑模板使用的属性
为什么默认情况下更改检测会这样工作?
Angular 的主要目标之一是更加透明和易于使用,因此框架用户不必费尽心思调试框架并了解内部机制即可有效地使用它。
如果 Angular 默认更改检测机制基于组件输入的参考比较而不是默认机制,那会是什么情况?即使是像 TODO 应用程序这样简单的东西也很难构建:开发人员必须非常小心地创建一个新的 Todo,而不是简单地更新属性。
OnPush
变化检测策略
如果你觉得默认模式影响了性能,我们也可以自定义 Angular 更改检测。将组件更改检测策略更新为OnPush
:
@Component({ selector: 'todo-list', changeDetection: ChangeDetectionStrategy.OnPush, template: ... }) export class TodoList { ... }
现在让我们在应用程序中添加几个按钮:一个是通过直接改变列表的第一项来切换列表的第一项,另一个是向整个列表添加一个 Todo。代码如下所示:
@Component({ selector: 'app', template: `<div> <todo-list [todos]="todos"></todo-list> </div> <button (click)="toggleFirst()">Toggle First Item</button> <button (click)="addTodo()">Add Todo to List</button>` }) export class App { todos:Array = initialData; constructor() { } toggleFirst() { this.todos[0].completed = ! this.todos[0].completed; } addTodo() { let newTodos = this.todos.slice(0); newTodos.push( new Todo(1, "TODO 4", false, new Owner("John", "Doe"))); this.todos = newTodos; } }
现在让我们看看这两个新按钮的行为:
- 第一个按钮“切换第一项”不起作用!这是因为该
toggleFirst()
方法直接改变了列表中的一个元素。TodoList
无法检测到这一点,因为它的输入参考todos
没有改变 - 第二个按钮确实有效!请注意,该方法
addTodo()
创建了 todo 列表的副本,然后将项目添加到副本中,最后将 todos 成员变量替换为复制的列表。这会触发更改检测,因为组件检测到其输入中的参考更改:它收到了一个新列表! - 在第二个按钮中,直接改变 todos 列表是行不通的!我们真的需要一个新的清单。
OnPush
只是通过引用比较输入吗?
情况并非如此。当使用 OnPush 检测器时,框架将在 OnPush 组件的任何输入属性更改、触发事件或 Observable 触发事件时检查
尽管允许更好的性能,但OnPush
如果与可变对象一起使用,则使用会带来很高的复杂性成本。它可能会引入难以推理和重现的错误。但是有一种方法可以使使用OnPush
可行。
使用 Immutable.js 简化 Angular 应用程序的构建
如果我们只使用不可变对象和不可变列表来构建我们的应用程序,则可以OnPush
透明地在任何地方使用,而不会遇到更改检测错误的风险。这是因为对于不可变对象,修改数据的唯一方法是创建一个新的不可变对象并替换之前的对象。使用不可变对象,我们可以保证:
- 新的不可变对象将始终触发
OnPush
更改检测 - 我们不会因为忘记创建对象的新副本而意外创建错误,因为修改数据的唯一方法是创建新对象
实现不可变的一个不错的选择是使用Immutable.js库。该库为构建应用程序提供了不可变原语,例如不可变对象(映射)和不可变列表。
避免变更检测循环:生产与开发模式
Angular 更改检测的重要属性之一是,与 AngularJs 不同,它强制执行单向数据流:当我们的控制器类上的数据更新时,更改检测运行并更新视图。
如何在 Angular 中触发变更检测循环?
一种方法是如果我们使用生命周期回调。例如,在TodoList组件中,我们可以触发对另一个组件的回调来更改其中一个绑定:
ngAfterViewChecked() { if (this.callback && this.clicked) { console.log("changing status ..."); this.callback(Math.random()); } }
控制台中将显示一条错误消息:
EXCEPTION: Expression '{{message}} in App@3:20' has changed after it was checked
仅当我们在开发模式下运行 Angular 时才会抛出此错误消息。如果我们启用生产模式会发生什么? 在生产模式下,错误不会被抛出,问题也不会被发现。
在开发阶段始终使用开发模式会更好,因为这样可以避免问题。这种保证是以 Angular 总是运行两次变更检测为代价的,第二次检测这种情况。在生产模式下,变更检测只运行一次。
打开/关闭变化检测,并手动触发它
在某些特殊情况下,我们确实想要关闭更改检测。想象一下这样一种情况,大量数据通过 websocket 从后端到达。我们可能只想每 5 秒更新一次 UI 的某个部分。为此,我们首先将更改检测器注入到组件中:
constructor(private ref: ChangeDetectorRef) { ref.detach(); setInterval(() => { this.ref.detectChanges(); }, 5000); }
正如我们所看到的,我们只是分离了变化检测器,这有效地关闭了变化检测。然后我们只需每 5 秒通过调用手动触发它detectChanges()
。
现在让我们快速总结一下我们需要了解的关于 Angular 变更检测的所有内容:它是什么,它是如何工作的以及可用的主要变更检测类型是什么。
概括
Angular 更改检测是一个内置的框架功能,可确保组件数据与其 HTML 模板视图之间的自动同步。
更改检测的工作原理是检测常见的浏览器事件,如鼠标点击、HTTP 请求和其他类型的事件,并确定每个组件的视图是否需要更新。
变更检测有两种类型:
- 默认更改检测:Angular 通过比较事件发生前后的所有模板表达式值来决定是否需要更新视图,用于组件树的所有组件
- OnPush 更改检测:这通过检测是否已通过组件输入或使用异步管道订阅的 Observable 将某些新数据显式推送到组件中来工作
Angular默认更改检测机制实际上与 AngularJs 非常相似:它比较浏览器事件之前和之后模板表达式的值,以查看是否有更改。它对所有组件都这样做。但也有一些重要的区别:
一方面,没有变化检测循环,也没有 AngularJs 中命名的摘要循环。这允许仅通过查看其模板和控制器来推理每个组件。
另一个区别是,由于变化检测器的构建方式,检测组件变化的机制要快得多。
最后,与 AngularJs 不同的是,变化检测机制是可定制的。
更多编程相关知识,请访问:编程教学!!
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Outils d'IA chauds

Undresser.AI Undress
Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover
Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool
Images de déshabillage gratuites

Clothoff.io
Dissolvant de vêtements AI

Video Face Swap
Échangez les visages dans n'importe quelle vidéo sans effort grâce à notre outil d'échange de visage AI entièrement gratuit !

Article chaud

Outils chauds

Bloc-notes++7.3.1
Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise
Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1
Puissant environnement de développement intégré PHP

Dreamweaver CS6
Outils de développement Web visuel

SublimeText3 version Mac
Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Le service Node construit sur une base non bloquante et piloté par les événements présente l'avantage d'une faible consommation de mémoire et est très adapté à la gestion de requêtes réseau massives. Dans le contexte de demandes massives, les questions liées au « contrôle de la mémoire » doivent être prises en compte. 1. Le mécanisme de récupération de place du V8 et les limitations de mémoire Js sont contrôlés par la machine de récupération de place

Vue.js est devenu aujourd'hui un framework très populaire dans le développement front-end. À mesure que Vue.js continue d'évoluer, les tests unitaires deviennent de plus en plus importants. Aujourd'hui, nous allons explorer comment écrire des tests unitaires dans Vue.js 3 et fournir quelques bonnes pratiques ainsi que des problèmes et solutions courants.

Le module de fichiers est une encapsulation des opérations de fichiers sous-jacentes, telles que l'ajout de lecture/écriture/ouverture/fermeture/suppression de fichiers, etc. La plus grande caractéristique du module de fichiers est que toutes les méthodes fournissent deux versions de **synchrone** et ** asynchrone**, with Les méthodes avec le suffixe sync sont toutes des méthodes de synchronisation, et celles qui n'en ont pas sont toutes des méthodes hétérogènes.

Le cross-domaine est un scénario souvent rencontré en développement, et c'est également une question souvent abordée lors des entretiens. La maîtrise des solutions interdomaines communes et des principes qui les sous-tendent peut non seulement améliorer notre efficacité de développement, mais également mieux performer lors des entretiens.

PHP et Vue : une combinaison parfaite d'outils de développement front-end À l'ère actuelle de développement rapide d'Internet, le développement front-end est devenu de plus en plus important. Alors que les utilisateurs ont des exigences de plus en plus élevées en matière d’expérience des sites Web et des applications, les développeurs front-end doivent utiliser des outils plus efficaces et plus flexibles pour créer des interfaces réactives et interactives. En tant que deux technologies importantes dans le domaine du développement front-end, PHP et Vue.js peuvent être considérés comme une arme parfaite lorsqu'ils sont associés. Cet article explorera la combinaison de PHP et Vue, ainsi que des exemples de code détaillés pour aider les lecteurs à mieux comprendre et appliquer ces deux éléments.

Au début, JS ne fonctionnait que du côté du navigateur. Il était facile de traiter les chaînes codées en Unicode, mais il était difficile de traiter les chaînes binaires et non codées en Unicode. Et le binaire est le format de données le plus bas du package ordinateur, vidéo/audio/programme/réseau.

Lors des entretiens de développement front-end, les questions courantes couvrent un large éventail de sujets, notamment les bases HTML/CSS, les bases JavaScript, les frameworks et les bibliothèques, l'expérience du projet, les algorithmes et les structures de données, l'optimisation des performances, les requêtes inter-domaines, l'ingénierie front-end, les modèles de conception et les nouvelles technologies et tendances. Les questions de l'intervieweur sont conçues pour évaluer les compétences techniques du candidat, son expérience en matière de projet et sa compréhension des tendances du secteur. Par conséquent, les candidats doivent être parfaitement préparés dans ces domaines pour démontrer leurs capacités et leur expertise.

Avec le développement de la technologie Internet, le développement front-end est devenu de plus en plus important. La popularité des appareils mobiles, en particulier, nécessite une technologie de développement frontal efficace, stable, sûre et facile à entretenir. En tant que langage de programmation en développement rapide, le langage Go est utilisé par de plus en plus de développeurs. Alors, est-il possible d’utiliser le langage Go pour le développement front-end ? Ensuite, cet article expliquera en détail comment utiliser le langage Go pour le développement front-end. Voyons d’abord pourquoi le langage Go est utilisé pour le développement front-end. Beaucoup de gens pensent que le langage Go est un
