Angular2:观察角度之外的外部变量

Posted

技术标签:

【中文标题】Angular2:观察角度之外的外部变量【英文标题】:Angular2: Watch an external variable outside of angular 【发布时间】:2016-08-18 03:39:33 【问题描述】:

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

var test = 1;

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

@Component(
   ...
)

export class MyComponent 
    watchy = window.test;

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

【问题讨论】:

【参考方案1】:

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

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

您需要手动调用更改检测,以便 Angular 识别更改的变量。另见Triggering Angular2 change detection manually

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

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

调用的事件处理程序会自动调用 Angulars 更改检测,因此无需执行更多操作。

【讨论】:

app/app.component.ts(96,12):错误 TS2339:“AppComponent”类型上不存在属性“watchy”。 我猜这是一个 linter 警告。只需在类上声明属性,你就应该很好。 我是新手,从最近两天开始,我收到了这些错误。当我尝试 deciare 时,我遇到了一些其他错误。 piease什么是deciare的正确方法 对不起,我的回答有误。应该是event.detail,感谢您的提示。 这段代码,如所写,仅适用于按钮/点击/等事件。如果您只是尝试通过事件发送消息(数据),您现在使用window.dispatchEvent(new CustomEvent('test', detail: 'newValue')); 注意,它使用的是 CustomEvent,而不是 Event。 detail 属性只能通过 CustomEvent 获得。您可以查看此 API 和更多详细信息:developer.mozilla.org/en-US/docs/Web/API/CustomEvent/…【参考方案2】:

根据this answer,显然这应该可以工作。

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

watchy = window.test;

将创建一个原始类型的组件属性。当那行代码执行时,watchy 将被赋值为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 的值,则需要在 Angular 区域内更改 test 才能运行更改检测并注意到更改。不要在这里重复一堆代码,请参阅Angular 2 How to get Angular to detect changes made outside Angular?


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

【讨论】:

【参考方案3】:

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

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

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

export class MyComponent 
    watchy = window.test;

   onClickEvent() 
    this.watchy = window.test;
  

然后改变var,触发click事件,就可以工作了。

【讨论】:

以上是关于Angular2:观察角度之外的外部变量的主要内容,如果未能解决你的问题,请参考以下文章

Angular 2:变量名是啥?意思是?

角度 2 ngIf 与可观察?

角度 2.0 相当于 $scope.$apply

Webpack - 在 Angular 2 中调用外部 JS

BrowserDomAdapter 更改没有反映在 angular2 上下文的外部

使用指令检测角度 4 中的 Click 外部元素