对 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 区域之外进行更改,就会触发该事件。
我有一个使用相当基础的 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 对象,然后调用该区域的 运行 函数。
请参考
Is this just an awful idea?
是的。
Angular 的自动更改检测系统假设数据更改(您希望组件显示)发生在由 Zone.js 猴子修补的事件处理程序中。因为那时 Angular 的更改检测将在此类事件处理程序触发时执行(好吧,从技术上讲,它将在事件处理程序完成后执行)。
如果您希望组件视图自动更新,您必须更改 Angular 内的绑定数据 – 在 Angular 区域内。正如@Jigar 回答的那样,您可以修改代码以调用 angularZone.run(_ => // make changes here)
,但如果必须这样做,您不妨将管理和操作数据的代码移动到服务(或组件,如果逻辑是最小的)。
另见