changeDetection:ChangeDetectionStrategy.OnPush 似乎不起作用?
changeDetection: ChangeDetectionStrategy.OnPush doesn't seem to be working?
https://stackblitz.com/edit/angular-xpamld
问题:有人能帮我理解为什么我的原型 changeDetection: ChangeDetectionStrategy.OnPush
仍然允许我更新内部值 name
吗?如果这不是 ChangeDetectionStrategy.OnPush
应该阻止的,它应该做什么?
app.component.ts:
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AppComponent {
public name = 'Angular 5';
public changeName() {
this.name = 'Outer';
}
}
app.component.html:
<hello name="{{ name }}"></hello>
<button (click)="changeName()">Outter Change</button>
<p>{{name}}-- outer</p>
<p>
Start editing to see some magic happen :)
</p>
hello.component.ts:
@Component({
selector: 'hello',
template: `<h1>Hello {{name}}!</h1> <button (click)="changeName()">inner Change</button>`,
styles: [`h1 { font-family: Lato; }`],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class HelloComponent {
@Input() name: string;
public changeName() {
this.name = 'Inner';
}
}
因为原始数据类型是不可变的 - 如果你改变它,它的引用也会改变,所以你的组件 ChangeDetectorRef
知道它必须检测变化(因为 OnPush
查找引用变化,而不是数据变化在数组、对象中)。如果你想在基元上避免这种情况,你可以在 ChangeDetectorRef 实例上手动 deactivate/activate this with detach()
/ reattach()
:
import { ChangeDetectorRef } from '@angular/core';
export class HelloComponent {
@Input() name: string;
constructor(private ref: ChangeDetectorRef) {}
public changeName() {
this.ref.detach();
this.name = 'Inner';
}
}
The state is updated only if parent view bindings changed and child
component view was initialized with ChangeDetectionStrategy.OnPush.
在您所说的示例中,只需将以下行添加到子 Hello 组件。
ngOnChanges(simpleChange : SimpleChanges){
console.log(simpleChange)
}
您会看到,单击按钮后,视图随着父绑定发生更改而发生变化,这就是视图在父绑定和子绑定中更新的原因。
默认的更改检测策略是保守的,并检查其所有绑定以查找可能已更改的内容。通常,只要 [input] 发生变化,或者 (event) 发生在 any 组件.
通过将组件的更改检测策略更改为 OnPush,Angular 仅在组件的输入 具有居然改了。这允许 Angular 通过允许在变更检测期间跳过整个子树来更有效地进行变更检测。
这里有一篇关于它的好文章:https://vsavkin.com/immutability-vs-encapsulation-90549ab74487
一些有助于理解的要点是:
- 默认情况下,当触发更改检测摘要时,将检查所有绑定是否有来自所有组件的更新,无论更改最初来自何处。
- 发生变化检测以建立原始绑定(输入绑定),或者它可以由浏览器事件触发(即输出绑定)。一旦触发,#1 应用。
- 变化检测是自上而下发生的,从根组件开始到叶子。将其视为连接组件的单向树,它以 AppComponent 为根。
- 当组件的变更检测策略更改为
OnPush
时,在变更检测期间,如果输入未更改,它将跳过组件的整个子树。
https://stackblitz.com/edit/angular-xpamld
问题:有人能帮我理解为什么我的原型 changeDetection: ChangeDetectionStrategy.OnPush
仍然允许我更新内部值 name
吗?如果这不是 ChangeDetectionStrategy.OnPush
应该阻止的,它应该做什么?
app.component.ts:
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AppComponent {
public name = 'Angular 5';
public changeName() {
this.name = 'Outer';
}
}
app.component.html:
<hello name="{{ name }}"></hello>
<button (click)="changeName()">Outter Change</button>
<p>{{name}}-- outer</p>
<p>
Start editing to see some magic happen :)
</p>
hello.component.ts:
@Component({
selector: 'hello',
template: `<h1>Hello {{name}}!</h1> <button (click)="changeName()">inner Change</button>`,
styles: [`h1 { font-family: Lato; }`],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class HelloComponent {
@Input() name: string;
public changeName() {
this.name = 'Inner';
}
}
因为原始数据类型是不可变的 - 如果你改变它,它的引用也会改变,所以你的组件 ChangeDetectorRef
知道它必须检测变化(因为 OnPush
查找引用变化,而不是数据变化在数组、对象中)。如果你想在基元上避免这种情况,你可以在 ChangeDetectorRef 实例上手动 deactivate/activate this with detach()
/ reattach()
:
import { ChangeDetectorRef } from '@angular/core';
export class HelloComponent {
@Input() name: string;
constructor(private ref: ChangeDetectorRef) {}
public changeName() {
this.ref.detach();
this.name = 'Inner';
}
}
The state is updated only if parent view bindings changed and child component view was initialized with ChangeDetectionStrategy.OnPush.
在您所说的示例中,只需将以下行添加到子 Hello 组件。
ngOnChanges(simpleChange : SimpleChanges){
console.log(simpleChange)
}
您会看到,单击按钮后,视图随着父绑定发生更改而发生变化,这就是视图在父绑定和子绑定中更新的原因。
默认的更改检测策略是保守的,并检查其所有绑定以查找可能已更改的内容。通常,只要 [input] 发生变化,或者 (event) 发生在 any 组件.
通过将组件的更改检测策略更改为 OnPush,Angular 仅在组件的输入 具有居然改了。这允许 Angular 通过允许在变更检测期间跳过整个子树来更有效地进行变更检测。
这里有一篇关于它的好文章:https://vsavkin.com/immutability-vs-encapsulation-90549ab74487
一些有助于理解的要点是:
- 默认情况下,当触发更改检测摘要时,将检查所有绑定是否有来自所有组件的更新,无论更改最初来自何处。
- 发生变化检测以建立原始绑定(输入绑定),或者它可以由浏览器事件触发(即输出绑定)。一旦触发,#1 应用。
- 变化检测是自上而下发生的,从根组件开始到叶子。将其视为连接组件的单向树,它以 AppComponent 为根。
- 当组件的变更检测策略更改为
OnPush
时,在变更检测期间,如果输入未更改,它将跳过组件的整个子树。