我在angular2应用程序中遇到了一个非常有趣的东西,我简化了这里的情况。
这是AppComponnet
export class AppComponent {
tabs: any = [];
viewModes = [
{ label: "列表查看"},
{ label: "树状图" },
];
constructor(private changeRef: ChangeDetectorRef) {}
addTab() {
var worker = new Worker("worker.js");
worker.postMessage("");
worker.onmessage = (event) => {
this.tabs.push({
label: 'label'
})
this.changeRef.detectChanges();
}
}
currentMode: any;
selectViewMode(mode: any) {
if (this.currentMode) {
this.currentMode.selected = false;
}
mode.selected = true;
this.currentMode = mode;
}
}
这是模板
<div *ngFor="let tab of tabs">
<ul>
<li *ngFor="let item of viewModes">
<a (click)="selectViewMode(item)" [style.background]="item.selected ? '#f69c55' : ''"> {{item.label}} </a>
</li>
</ul>
</div>
<button (click)="addTab()">Add Tab</button>
当工作人员完成时,我将新选项卡推送到选项卡。并且angular2在Worker onmessage回调后不会进行更改检测,我必须手动触发更改检测。
但在此之后,添加的选项卡中列表的背景在点击后不会发生变化(回调函数已执行,因此更改检测不起作用)。
如果我再次单击“添加标签”按钮,则更改检测将起作用并按预期设置列表背景。
如果我不手动触发变化检测。推动标签后,执行其他操作(例如,再次单击按钮)以触发更改检测。现在列表将显示,背景更改效果很好。
我知道密钥是在工人执行后手动调用更改检测,但我不知道详细情况发生了什么导致列表背景更改检测不起作用。
答案 0 :(得分:2)
每次调用“添加”选项卡函数时,都在调用新工作程序。
addTab() {
var worker = new Worker("worker.js");
相反,将此工作者声明为此类和范围的范围绑定变量。在函数中使用它。
worker : any = new Worker("worker.js");
addTab() {
this.worker.postMessage("");
this.worker.onmessage = (event) => {
this.tabs.push({
label: 'label'
})
答案 1 :(得分:1)
NgZone
修补了setTimeout
或addEventListener
等异步API。当调用此类API的回调时,Angular会识别它并运行更改检测。
显然worker.onmessage
未涵盖NgZone
,因此不会调用更改检测。
有多种方法可以调用更改检测Triggering Angular2 change detection manually
detectChanges()
仅调用当前元素的变化检测。
如果模型更改具有更广泛的影响(在组件外部),那么您可能需要运行应用程序范围的更改检测(例如,如果您从在Angulars区域外运行的回调router.navigate()
(未由{{1}覆盖}。
在这种情况下,您可以使代码在区域内运行,如
NgZone