AngularJS:是否可以观看全局变量(即范围外)? [英] AngularJS: Is it possible to watch a global variable (I.e outside a scope)?
问题描述
首先让我说我正在尝试做的事情可能不被认为是好的做法.但是,我需要做这样的事情,以便以小的增量步骤将大型 Web 应用迁移到 AngularJs.
Let me start by saying that what I am trying to do is probably not considered good practice. However, I need to do something like this in order to migrate a large web app to AngularJs in small incremental steps.
我尝试过
$scope.$watch(function () { return myVar; }, function (n, old) {
alert(n + ' ' + old);
});
其中 myVar 是全局变量(在窗口上定义)
Where myVar is a global variable (defined on window)
然后从控制台更改 myVar.但它只在第一次设置观察者时触发.
And then changing myVar from the console. But it only fires when first setting up the watcher.
如果我从控制器中更新 myVar 就可以工作(请参阅 http://jsfiddle.net/rasmusvhansen/vsDXz/3/,但如果它是从某些旧版 javascript 更新的,则不会
It works if I update myVar from within the controller (see http://jsfiddle.net/rasmusvhansen/vsDXz/3/, but not if it is updated from some legacy javascript
有什么办法可以实现吗?
Is there any way to achieve this?
更新如果遗留代码完全不受限制,我喜欢安德斯的回答.但是,目前我正在研究这种似乎有效并且不包括每秒触发的计时器的方法:
Update I like Anders' answer if the legacy code is completely off limits. However, at the moment I am looking at this approach which seems to work and does not include a timer firing every second:
// In legacy code when changing stuff
$('.angular-component').each(function () {
$(this).scope().$broadcast('changed');
});
// In angular
$scope.$on('changed', function () {
$scope.reactToChange();
});
尽管我会选择其他解决方案,但我还是要给 Anders 加分,因为他的解决方案正确地解决了上述问题.
I am awarding points to Anders even though I will go with another solution, since his solution correctly solves the problem stated.
推荐答案
这里的问题可能是您正在从 Angular 世界之外修改 myVar
.Angular 不会一直运行摘要循环/脏检查,只有当应用程序中发生应该触发摘要的事情时,例如 Angular 知道的 DOM 事件.因此,即使 myVar
发生了变化,Angular 也没有理由开始新的摘要循环,因为什么都没有发生(至少 Angular 知道).
The issue here is probably that you're modifying myVar
from outside of the Angular world. Angular doesn't run digest cycles/dirty checks all the time, only when things happen in an application that should trigger a digest, such as DOM events that Angular knows about. So even if myVar
has changed, Angular sees no reason to start a new digest cycle, since nothing has happened (at least that Angular knows about).
因此,为了触发您的手表,您需要在更改 myVar
时强制 Angular 运行摘要.但这会有点麻烦,我认为您最好创建一个全局可观察对象,如下所示:
So in order to fire your watch, you need to force Angular to run a digest when you change myVar
. But that would be a bit cumbersome, I think you would be better of to create a global observable object, something like this:
<!doctype html>
<html ng-app="myApp">
<head>
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="http://code.angularjs.org/1.0.5/angular.min.js"></script>
<script>
// Outside of Angular
window.myVar = {prop: "value1"};
var myVarWatch = (function() {
var watches = {};
return {
watch: function(callback) {
var id = Math.random().toString();
watches[id] = callback;
// Return a function that removes the listener
return function() {
watches[id] = null;
delete watches[id];
}
},
trigger: function() {
for (var k in watches) {
watches[k](window.myVar);
}
}
}
})();
setTimeout(function() {
window.myVar.prop = "new value";
myVarWatch.trigger();
}, 1000);
// Inside of Angular
angular.module('myApp', []).controller('Ctrl', function($scope) {
var unbind = myVarWatch.watch(function(newVal) {
console.log("the value changed!", newVal);
});
// Unbind the listener when the scope is destroyed
$scope.$on('$destroy', unbind);
});
</script>
</head>
<body ng-controller="Ctrl">
</body>
</html>
这篇关于AngularJS:是否可以观看全局变量(即范围外)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!