Angular 4 - “等待操作”的正确方法是什么? [英] Angular 4 - What is the right way to "wait for operation"?
问题描述
我遇到了一个简单的问题,它有一个hacky解决方案 setTimeout(...,0)
。
查看这个简单的代码:
@Component({
selector: 'my-app',
template: `
<div>
<input value='Fill Data' type='button' (click)='fill()'/>
<span *ngFor="let o of Items" class='mySpan'>Span To Detect<br></span>
</div>
`,
})
export class App {
Items:Array<number> = new Array<number>();
fill()
{
this.Items = [1,2,3,4,5,6,7,8,9,10]
this.analyzeDom(); //this has to run here
}
analyzeDom()
{
alert($("div .mySpan").length) // "0"
//BUT if I set this hacky trick , it works
// setTimeout(function (){ alert($("div .mySpan").length)},0) // "10"
}
}
如果我点击按钮,警报显示0。我明白为什么会这样。这是因为Angular没有完成其循环来实际填充 ngFor
。
If I click the button , the alert shows "0". I understand why it's happening. It's becuase Angular didn't complete its cycle to actually populate the ngFor
.
然而 - 用<做这个技巧code> setTimeout(..,0)对我来说似乎有些苛刻,我不想相信它。
However - doing this trick with setTimeout(..,0)
seems a bit hacky to me and I prefer not to trust on it.
问题:
Angular中等待操作的正确方法是什么? (所以我会看到10)?
What is the right way to "wait for operation" in Angular ? (so that I'll see "10") ?
推荐答案
1)您可以强制Angular更新DOM通过调用 cdRef.detectChanges
1) You can force Angular to update the DOM by calling cdRef.detectChanges
constructor(private cdRef: ChangeDetectorRef) {}
analyzeDom(){
this.cdRef.detectChanges();
alert($("div .mySpan").length)
< a href =http://plnkr.co/edit/XFlV5saTLtiNT8QPOlCO?p=preview =nofollow noreferrer> Plunker
Plunker
因为 setTimeout
是macrotask因此它正在运行下一个摘要周期。
这意味着在调用 setTimeout
之后,将检查所有组件树
As setTimeout
is macrotask therefore it is running next digest cycle.
It means that after calling setTimeout
all components tree will be checked
cdRef.detectChanges
不会调用 appRef.tick()
。它只执行变更检测组件本身及其子项。
cdRef.detectChanges
doesn't call appRef.tick()
. It only executes change detection component itself and its children.
2)或者您可以等到Angulat通过订阅 zone.onMicrotaskEmpty来更新DOM / code>
2) or you can wait until Angulat has updated DOM by subscribing to zone.onMicrotaskEmpty
import 'rxjs/add/operator/first';
constructor(private zone: NgZone) {}
...
this.zone.onMicrotaskEmpty.first().subscribe(() => this.analyzeDom());
注意:第一个操作符可能导致内存泄漏。请参阅 https://github.com/angular/material2/issues/6905
订阅 onMicrotaskEmpty
不会调用更改检测周期
Subscribing to onMicrotaskEmpty
doesn't call change detection cycle
< a href =http://plnkr.co/edit/1MS3w4GP7zv5tYZD2hn8?p=preview =nofollow noreferrer> Plunker
Plunker
这篇关于Angular 4 - “等待操作”的正确方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!