为什么我的Angular 2 * ngIf在功能完成之前无法渲染?

时间:2017-02-10 20:16:09

标签: angular angular2-template

我有以下代码......

// Pug Template
.notification-header-area.layout-row.layout-align-center-center( *ngIf="notification.message != null", class="{{notification.color}}" )

// Inside angular component
private onNotificationStart = (notification) => {
        this.notification = notification;
        console.log(this.myElement.nativeElement);
        if (this.myElement.nativeElement.children.length > 0) {
            // TODO: We should probably do this in a more reliable way in case the template changes.
            let elm = this.myElement.nativeElement.children[0];
            if (notification.fontSize) elm.style.fontSize = notification.fontSize;
            if (notification.colorBackground) elm.style.backgroundColor = notification.colorBackground;
            if (notification.colorFont) elm.style.color = notification.colorFont;
        }
}

问题是如果我在控制台行调试,浏览器不会显示通知dom元素。在写出对象时,console.log语句也会丢失它。如果函数完成运行,则ngIf呈现自身,并且我按预期看到该元素。是否有$ timeout等价物?我从Web套接字获取此事件并尝试Trouble with *ngIf in Angular 2 (TypeScript)但它无法正常工作。我也无法在我的简单的plunker(没有使用网络套接字)中重新创建它,所以我仍然在寻找一个演示。

此外,如果我像这样包装一个超时工作......

private onNotificationStart = (notification) => {
    this.notification = notification;
    setTimeout(() => {
       console.log(this.myElement.nativeElement);
        if (this.myElement.nativeElement.children.length > 0) {
            // TODO: We should probably do this in a more reliable way in case the template changes.
            let elm = this.myElement.nativeElement.children[0];
            if (notification.fontSize) elm.style.fontSize = notification.fontSize;
            if (notification.colorBackground) elm.style.backgroundColor = notification.colorBackground;
            if (notification.colorFont) elm.style.color = notification.colorFont;
        }
    })
    // if(notification){
    //     this.myElement.nativeElement.style.backgroundColor =
    // }
} 

2 个答案:

答案 0 :(得分:1)

简短回答:在这两种情况下,一切都按预期进行。如果你的期望不同那么他们就错了。

再长一点......

你不能指望角度做一些魔法或比执行它的浏览器更聪明。 :)如果我们简化一点...... Javascript总是只有一个执行线程(不考虑Web工作者)。当您更改函数内部的通知标志时,在您的函数完成之前,外部世界不会发生任何事情,因为它会阻止唯一可用的执行线程。只有在此之后,稍后在某个时间点,更改检测才会启动并执行所有视图同步,组件创建或销毁以及必须完成的所有其他操作。这就是它与setTimeout()一起工作的原因 - 它为所有这些事情提供了机会。

答案 1 :(得分:1)

Angular2(和4)使用zone.js修补异步API,例如addEventHandlersetTimeout,....每当发生事件或setTimeout或其他异步API调用时,Angular处理程序方法完成后运行更改检测。更改检测会导致更新视图(绑定)。这也是*ngIf更新时的情况。因此,在更新绑定变量的方法结束后更新*ngIf正是预期的行为。

<强>更新

回调可能在Angulars区域外运行,因为zone.js可能不包含Web套接字API。 您可以注入private zone:NgZone并使用

包装代码
this.zone.run(() => wrapped code here)

或注入private cdRef:ChangeDetectorRef并致电

this.cdRef.detectChanges();
更新绑定字段以显式调用更改检测后