1

我有一个用相当基本的 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);
    });
}());
4

3 回答 3

2

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

是的。

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

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

另请参阅Günter 的替代方法:在 Angular 内(因此在 Angular 区域内)设置一个事件侦听器。然后每当您在 Angular 区域之外进行更改时触发该事件。

于 2016-04-20T21:56:14.497 回答
1

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

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

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

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

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

于 2016-04-18T08:25:28.770 回答
1

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

请参阅Angular 2 如何让 Angular 检测在 Angular 之外所做的更改?所以问题

于 2016-04-20T04:16:39.133 回答