对 Angular2 之外所做的更改做出反应

Reacting to changes made outside of Angular2

我有一个使用相当基础的 JS 制作的非 angular 页面,我认为尝试添加学习一些 Angular2 并将其用于一些新功能是一个绝妙的主意。

我的计划是将一个 Angular2 组件绑定到一个由旧代码更新的对象,然后我将使用 Angular2 魔法来更新一块 ​​UI.

问题是我无法说服 Angular2 对外部 JS 中所做的任何更改做出反应。这样做有什么诀窍?尝试用谷歌搜索这个问题导致对 Angular2 的变化检测过程的深入解释,到目前为止这还没有帮助。这是一个糟糕的主意吗?

我发现了一个随机的 Angular2 jsfiddle 并将其破解以显示问题。字符串被添加到 'window.names',但直到从 angular 侧添加一个字符串:https://jsfiddle.net/byfo3jg3/ 后,您才会看到它们。代码如下:

var names = ['Joe'];

setTimeout(function() {
  names.push("Frank");
}, 1000);

setTimeout(function() {
  names.push("Sterve");
}, 2000);

setTimeout(function() {
  names.push("Garfield");
}, 3000);

(function() {
  var HelloApp,
        ListThing;

    ListThing = ng
        .Component({
            selector: 'list-thing',
            template: '<ul><li *ng-for="#name of names">{{name}}</li></ul>',
            directives: [ng.NgFor]
        })
        .Class({
            constructor: function() {
                this.names = window.names;

        setTimeout(function() {
                    this.names.push("Oh hai");
                }.bind(this), 10000);
            }
        });

    HelloApp = ng
        .Component({
            selector: 'hello-app',
            template: '<list-thing></list-thing>',
            directives: [ListThing]
        })
        .Class({
            constructor: function() {}
        });

    document.addEventListener('DOMContentLoaded', function() {
        ng.bootstrap(HelloApp);
    });
}());

names 应该是组件 属性 才能在模板内部工作:

constructor(){this.names = window.names}

window.names 的更改将不会被 angular 检测到,因此您几乎没有选择:使用 setInterval(()=>{this.names = window.names}, 1000) 轮询名称或公开全局回调:

constructor(zone:NgZone) 
{
   window.notify = ()=> {
        zone.run(()=> { 
                this.names = window.names;
        });
   }
 }

并从纯 js 调用它 window.notify() 或使用其他方法调用变化检测。

您需要将 NgZone 设置为 window 对象,然后调用该区域的 运行 函数。

请参考 SO问题

Is this just an awful idea?

是的。

Angular 的自动更改检测系统假设数据更改(您希望组件显示)发生在由 Zone.js 猴子修补的事件处理程序中。因为那时 Angular 的更改检测将在此类事件处理程序触发时执行(好吧,从技术上讲,它将在事件处理程序完成后执行)。

如果您希望组件视图自动更新,您必须更改 Angular 内的绑定数据 – 在 Angular 区域内。正如@Jigar 回答的那样,您可以修改代码以调用 angularZone.run(_ => // make changes here),但如果必须这样做,您不妨将管理和操作数据的代码移动到服务(或组件,如果逻辑是最小的)。

另见 :在 Angular 内设置一个事件侦听器(因此在 Angular 区域内)。然后,只要您在 Angular 区域之外进行更改,就会触发该事件。