对Angular2之外的更改做出反应

时间:2016-04-18 02:32:23

标签: data-binding angular angular2-changedetection

我已经使用相当基本的JS制作了一个非角度页面,并认为尝试添加学习一些Angular2并将其用于一些新功能是一个很棒的想法。

我的计划是将Angular2组件绑定到旧代码正在更新的对象上,并且我使用Angular2魔法来更新一大块UI。

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

我找到了一个随机的Angular2 jsfiddle并将其黑了以显示问题。字符串被添加到' window.names',但是在从角度边添加一个字符串之前你不会看到它们: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);
    });
}());

3 个答案:

答案 0 :(得分:2)

  

这只是一个糟糕的主意吗?

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

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

另请参阅Günter's alternative approach:在Angular中设置一个事件监听器(因此在Angular区域内)。然后,只要在Angular区域外进行更改,就会触发该事件。

答案 1 :(得分:1)

Object* obj = new Obj[rows * cols]; obj[x * cols + y]; 应该是在模板内部工作的组件属性:

names

角度不会检测到constructor(){this.names = window.names} 的更改,因此您几乎没有选项:使用window.names轮询名称或公开全局回调:

setInterval(()=>{this.names = window.names}, 1000)

并从普通js constructor(zone:NgZone) { window.notify = ()=> { zone.run(()=> { this.names = window.names; }); } } 调用它,或使用其他方法调用变更检测。

答案 2 :(得分:1)

您需要将NgZone设置为window对象,然后调用该区域的run function。

请参阅Angular 2 How to get Angular to detect changes made outside Angular? SO问题