7

我希望能够在 angular2 之外的变量发生变化时进行观察和更新。所以假设我在一个外部 javascript 文件中有这个:

var test = 1;

如何将此变量绑定到组件中的属性?

@Component({
   ...
})

export class MyComponent {
    watchy = window.test;
}

根据这个答案,显然这应该可以工作。
但事实并非如此。如果我在控制台中更改变量,该变量不会更新显示在模板中。我错过了什么吗?

4

3 回答 3

19

Angular 仅在异步执行的函数完成时运行更改检测。该函数需要在 Angulars 区域内运行,以便 Angular 识别异步操作。

因为您的变量是从 Angulars 区域之外更改的。Angular 不运行变更检测。

您需要手动调用更改检测,以便 Angular 识别更改的变量。另请参阅手动触发 Angular2 更改检测

例如,如果您可以调度事件而不是仅设置变量,则可以侦听该事件。

window.dispatchEvent(new CustomEvent('test', {detail: 'newValue'}));
@Component({
   ...
})
export class MyComponent {
    @HostListener('window:test', ['$event'])
    testListener(event) {
      this.watchy = event.detail;
    }
}

调用的事件处理程序会自动调用 Angulars 更改检测,因此没有什么可做的。

于 2016-04-25T04:37:44.503 回答
3

根据这个答案,显然这应该可以工作。

我不确定您是如何得出这个结论的,但无论如何,代码存在更大的问题。这行代码

watchy = window.test;

将创建一个原始类型的组件属性。当该行代码执行时,watchy将被分配 value 1watchy,因为它是一个原语,在赋值之后与它没有关系window.test——它只是获取window.test赋值的值的副本。因此,如果您随后更改 的值window.test,JavaScript 将不会更新watchy,因此 Angular 更改检测甚至不是这里的一个因素。

如果您希望组件属性链接到全局变量,您可以将原始类型包装在一个对象中:

var myObj = { test: 1}
export class MyComponent {
  watchy = window.myObj;
}

现在,watchy是一个引用类型,它引用myObj对象——它没有得到对象的副本,它只是“指向”它。因此,如果您随后更改myObj.test,那么 watchy 将“看到”新值,因为它仍然指向myObj.test对象。但是,如果您在 Angular 区域之外更改值,则 Angular 更改检测不会注意到。

如果您test在组件模板中显示 的值,则需要test在 Angular 区域内进行更改,以便更改检测运行并注意到更改。不要在这里重复一堆代码,请参阅Angular 2 如何让 Angular 检测在 Angular 之外所做的更改?


Günter 的回答是另一种方法:在 Angular 内(因此在 Angular 区域内)设置一个事件侦听器,然后在test发生更改时触发该事件。

于 2016-04-26T18:40:55.967 回答
0

这永远不会奏效。您需要告诉 Angular2 更新 watchy,有很多方法可以实现这一点,但是将它放在 Angular2 应用程序之外的全局变量中有点奇怪。

例如,您可以在一个函数中使用 watchy,该函数将在组件内元素的点击事件上触发,例如:

@Component({
   template: '<div (click)="onClickEvent()"></div>{{watchy}}'
})

export class MyComponent {
    watchy = window.test;

   onClickEvent() {
    this.watchy = window.test;
  }
}

然后更改var,触发click事件,它将起作用。

于 2016-04-24T22:29:57.323 回答