【问题标题】:Reacting to changes made outside of Angular2对 Angular2 之外所做的更改做出反应
【发布时间】:2016-08-09 15:17:07
【问题描述】:

我有一个用相当基本的 JS 制作的非 Angular 页面,并认为尝试添加一些 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);
    });
}());

【问题讨论】:

  • 我不建议这样做,除非你绝对必须这样做!否则,查看 Observables 并订阅组件中该数组的更改,当更改发生时更新组件数组。

标签: data-binding angular angular2-changedetection


【解决方案1】:

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

是的。

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

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

另见Günter's alternative approach:在 Angular 内(因此在 Angular 区域内)设置一个事件监听器。然后在您在 Angular 区域之外进行更改时触发该事件。

【讨论】:

    【解决方案2】:

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

    请参考Angular 2 How to get Angular to detect changes made outside Angular? SO Question

    【讨论】:

    • 虽然我决定听从 Mark 的建议,基本上尝试将我的更多应用程序转换为 Angular2 而不是回避它,但我认为这是第一个指向“Angular”的答案" 做我正在寻找的事情的方法。
    【解决方案3】:

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

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

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

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

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

    【讨论】:

    • notify() 的想法行不通,因为您将从 Angular 区域外部调用 notify(),因此不会运行更改检测。测试小提琴:jsfiddle.net/sv2xv7x0/2
    • 那么你可以很容易地在通知方法中添加zone.run
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-12
    相关资源
    最近更新 更多