首先,我想说我想做的事情可能不被认为是好的做法。但是,我需要执行类似的操作,以便以较小的增量步骤将大型Web应用程序迁移到AngularJs。
我试着做
$scope.$watch(function () { return myVar; }, function (n, old) { alert(n + ' ' + old); });
其中myVar是全局变量(在窗口上定义)
然后从控制台更改myVar。但是只有在首次设置观察者时才会触发。
如果我从控制器内部更新myVar(请参阅http://jsfiddle.net/rasmusvhansen/vsDXz/3/),则该方法有效,但如果它是从某些旧版javascript更新的,则无效
有什么办法可以做到这一点?
更新 如果遗留代码完全超出限制,我喜欢Anders的回答。但是,目前,我正在研究这种方法,该方法似乎有效,并且不包括每秒触发一次的计时器:
// In legacy code when changing stuff $('.angular-component').each(function () { $(this).scope().$broadcast('changed'); }); // In angular $scope.$on('changed', function () { $scope.reactToChange(); });
尽管我将使用其他解决方案,但我仍在向Anders奖励积分,因为他的解决方案可以正确解决所述问题。
这里的问题可能是您是myVar从Angular世界之外进行修改的。Angular不会一直运行摘要周期/脏检查,只有当应触发摘要的应用程序中发生某些事情时,例如Angular知道的DOM事件。因此,即使myVar发生了变化,Angular也没有理由开始新的摘要循环,因为什么也没发生(至少Angular知道)。
myVar
因此,为了触发您的手表,您需要在更改时强制Angular运行摘要myVar。但这有点麻烦,我认为您最好创建一个全局可观察对象,如下所示:
<!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>