2017-04-17 91 views
4

我遇到了一个简单的问题,它有一个简单的解决方案setTimeout(...,0)Angular 4 - 什么是“等待手术”的正确方法?

望着这个简单的代码:

@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)做这个诡计对我来说似乎有点冒失,我宁愿不相信它。

问:

什么是正确的方式在角 “等待作业”? (这样我会看到“10”)?

Plnkr

+0

通过使用[生命周期钩(https://angular.io/docs/ts/latest/guide/ lifecycle-hooks.html) - 'ngOnInit'或者不同的'ngDoCheck'方法 – mhodges

+0

@mhodges但是点击按钮可以点击这个按钮,并且在这些钩子已经发生之后可以点击这个按钮 –

+0

你想要的原因是什么使其同步和延迟功能,直到DOM将被更新?是不是更好地从当前模型读取长度,而不是像'alert(this.Items.length)'这样的DOM? – Kuba

回答

10

1)您可以强制角致电cdRef.detectChanges

constructor(private cdRef: ChangeDetectorRef) {} 

analyzeDom(){ 
    this.cdRef.detectChanges(); 
    alert($("div .mySpan").length) 

Plunker

至于setTimeout更新DOM是宏任务,因此它在运行下一个周期的消化。 这意味着在调用setTimeout后,所有组件树都将被检查

cdRef.detectChanges不会调用appRef.tick()。它只执行变更检测组件本身及其子项。

2),或者你可以等到Angulat已经通过订阅更新DOM来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不调用变更检测周期

Plunker

+0

你能解释如何不同'setTimeout(... 0)'是而不是你的解决方案? –

+1

@Royi setTimeout的工作原理是因为它将您传递给它的函数碰撞到下一个评估周期。因此,在您的代码中进行更改,然后Angular检测到这些更改并相应地更改DOM。在通过代码之后,执行超时函数。真的不是一个很糟糕的解决方案,只是它不是一个Angular解决方案,因此很难。上面列出的解决方案明确表示在dom更新后执行我的代码。 – SethWhite

+0

@SethWhite谢谢澄清,但是,我正在寻找一篇关于'onMicrotaskEmpty'的好文章(用于学习目的) - 仍然没有找到任何 –

相关问题