更新
ios – OnPush战略的组件在输入时被“更改检测到”
变化,EVEN IF 他们的变化检测器被分离。
因为Angular 4.1.1(2017-05-04)OnPush
应该尊重detach()
https://github.com/angular/angular/commit/acf83b9
旧版本
关于变更检测是如何工作的,有许多无证件的东西。
我们应该知道三个主要的changeDelections状态(cdMode
):
(1) 一次检查 -- -- 0
CheckedOnce
意味着在调用dectChange之后,
变更检测器将成为Checked
。
appview类
detectChanges(throwOnChange: boolean): void {
...
this.detectChangesInternal(throwOnChange);
if (this.cdMode === ChangeDetectorStatus.CheckOnce) {
this.cdMode = ChangeDetectorStatus.Checked; // <== this line
}
...
}
(2) 核对 -- -- 1
Checked
意味着变更检测器应该跳过,直到它的模式更改为CheckOnce
。
(3) 解雇-3
Detached
意味着变更检测器子树不是
主树应该跳过。
以下是使用Detached
的地方
appview类
跳过内容检查
detectContentChildrenChanges(throwOnChange: boolean) {
for (var i = 0; i < this.contentChildren.length; ++i) {
var child = this.contentChildren[i];
if (child.cdMode === ChangeDetectorStatus.Detached) continue; // <== this line
child.detectChanges(throwOnChange);
}
}
跳过视图检查
detectViewChildrenChanges(throwOnChange: boolean) {
for (var i = 0; i < this.viewChildren.length; ++i) {
var child = this.viewChildren[i];
if (child.cdMode === ChangeDetectorStatus.Detached) continue; // <== this line
child.detectChanges(throwOnChange);
}
}
跳过更改cdMode
到CheckOnce
markPathToRootAsCheckOnce(): void {
let c: AppView<any> = this;
while (isPresent(c) && c.cdMode !== ChangeDetectorStatus.Detached) { // <== this line
if (c.cdMode === ChangeDetectorStatus.Checked) {
c.cdMode = ChangeDetectorStatus.CheckOnce;
}
let parentEl =
c.type === ViewType.COMPONENT ? c.declarationAppElement : c.viewContainerElement;
c = isPresent(parentEl) ? parentEl.parentView : null;
}
}
注意:markPathToRootAsCheckOnce
在视图的所有事件处理程序中运行:
因此,如果将状态设置为 Detached
,那么您的视图就不会被更改。
然后如何工作OnPush
战略
OnPush
意味着变更检测器的模式将设置为CheckOnce
在水化过程中。
编译器/ src / view_compiler / property_binder.ts
const directiveDetectChangesStmt = isOnPushComp ?
new o.IfStmt(directiveDetectChangesExpr, [compileElement.appElement.prop('componentView')
.callMethod('markAsCheckOnce', [])
.toStmt()]) : directiveDetectChangesExpr.toStmt();
https://github.com/angular/angular/blob/2.1.2/modules/%40angular/compiler/src/view_compiler/property_binder.ts#L193-L197
让我们看看它在你的例子中的样子:
父工厂(AppComponent)
并再次返回appview类:
markAsCheckOnce(): void { this.cdMode = ChangeDetectorStatus.CheckOnce; }
设想1
1) OnPush Childron和Default Childron的Detach Change检测器(在两个组件上单击“detach()”)
OnPush.cdMode - Detached
3)单击“Change obj”将修改后的属性传递给子项
AppComponent.detectChanges
||
\/
//if (self._OnPush_35_4.detectChangesInInputProps(self,self._el_35,throwOnChange)) {
// self._appEl_35.componentView.markAsCheckOnce();
//}
OnPush.markAsCheckOnce
||
\/
OnPush.cdMode - CheckOnce
||
\/
OnPush.detectChanges
||
\/
OnPush.cdMode - Checked
因此OnPush.dectectChanges
正在射击.
这是结论:
javascript – 使用OnPush
策略的组件在它们时被“更改检测到”
输入变化,EVEN IF 它们的变化检测器被分离。
它将视图的状态更改为CheckOnce
.
设想2
(1) OnPush组件的Detach CD
OnPush.cdMode - Detached
6)单击“更改obj”将修改后的属性传递给
儿童
See 3) from scenario 1 => OnPush.cdMode - Checked
7)最后一次,编辑内部值输入并单击更改
内部:检测变更,更新内部值...
正如我上面提到的,所有事件处理程序都包括markPathToRootAsCheckOnce
.所以:
markPathToRootAsCheckOnce
||
\/
OnPush.cdMode - CheckOnce
||
\/
OnPush.detectChanges
||
\/
OnPush.cdMode - Checked
正如您所看到的 OnPush 策略和 ChangeDetector 管理一个属性 – cdMode
javascript – 使用OnPush策略的组件重新附加他们的变更检测器
每次他们的输入发生变化...
最后,我想说,你似乎是对的。