我遇到了一个简单的问题,它有一个 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
的周期。
但是 - 用 setTimeout(..,0)
来做这个技巧对我来说似乎有点老套,我不想相信它。
问题:
在 Angular 中“等待操作”的正确方法是什么? (这样我就会看到“10”)?
最佳答案
1) 您可以通过调用 cdRef.detectChanges
constructor(private cdRef: ChangeDetectorRef) {}
analyzeDom(){
this.cdRef.detectChanges();
alert($("div .mySpan").length)
由于 setTimeout
是宏任务,因此它会在下一个摘要周期运行。
这意味着在调用 setTimeout
之后所有的组件树都会被检查
cdRef.detectChanges
不调用 appRef.tick()
。它只执行变更检测组件本身及其子组件。
2) 或者您可以等到 Angulat 通过订阅 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
不调用变化检测周期
关于javascript - Angular 4 - "wait for operation"的正确方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43457149/