我希望能够在 angular2 之外的变量发生变化时进行观察和更新。所以假设我在一个外部 javascript 文件中有这个:
var test = 1;
如何将此变量绑定到组件中的属性?
@Component({
...
})
export class MyComponent {
watchy = window.test;
}
根据这个答案,显然这应该可以工作。
但事实并非如此。如果我在控制台中更改变量,该变量不会更新显示在模板中。我错过了什么吗?
我希望能够在 angular2 之外的变量发生变化时进行观察和更新。所以假设我在一个外部 javascript 文件中有这个:
var test = 1;
如何将此变量绑定到组件中的属性?
@Component({
...
})
export class MyComponent {
watchy = window.test;
}
根据这个答案,显然这应该可以工作。
但事实并非如此。如果我在控制台中更改变量,该变量不会更新显示在模板中。我错过了什么吗?
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 更改检测,因此没有什么可做的。
根据这个答案,显然这应该可以工作。
我不确定您是如何得出这个结论的,但无论如何,代码存在更大的问题。这行代码
watchy = window.test;
将创建一个原始类型的组件属性。当该行代码执行时,watchy
将被分配 value 1
。 watchy
,因为它是一个原语,在赋值之后与它没有关系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
发生更改时触发该事件。
这永远不会奏效。您需要告诉 Angular2 更新 watchy,有很多方法可以实现这一点,但是将它放在 Angular2 应用程序之外的全局变量中有点奇怪。
例如,您可以在一个函数中使用 watchy,该函数将在组件内元素的点击事件上触发,例如:
@Component({
template: '<div (click)="onClickEvent()"></div>{{watchy}}'
})
export class MyComponent {
watchy = window.test;
onClickEvent() {
this.watchy = window.test;
}
}
然后更改var,触发click事件,它将起作用。