我有一个在我的应用程序中观看按键的全局方法。当按键发生时,我像这样广播事件:
var keycodes = {
'escape': 27,
}
angular.element($window).on('keydown', function(e) {
for (var name in keycodes) {
if (e.keyCode === keycodes[name]) {
$rootScope.$broadcast('keydown-' + name, angular.element(e.target))
}
}
})
一切正常。在我的控制器中,我像这样倾听事件:
$rootScope.$on('keydown-escape', $scope.hideOverlays)
这也可以正常工作,但是,当我尝试更新$ scope对象的属性时,我没有在DOM中看到正确的行为:
$scope.hideOverlays = function() {
for (var i=0; i < $scope.gallery.items.length; i++) {
$scope.gallery.items[i].overlayShown = false;
$scope.gallery.items[i].editing = false;
}
}
当我从控制器内部调用此方法时,一切正常,所以我想知道Angular是否根据方法的调用方式做了不同的事情。我尝试过调用$ scope。$ apply()。除了看起来不是正确的事情,我也得到一个错误,所以没有骰子。非常感谢任何帮助!
答案 0 :(得分:1)
有很多缺少的代码会引发一些问题,例如,您在哪里执行keydown
事件,在我的示例中,您会看到我已将其放入app.run
中角:
// Note you have to inject $rootScope and $window
app.run(function ($rootScope, $window) {
angular.element($window).on('keydown', function (e) {
for (var name in keycodes) {
if (e.keyCode === keycodes[name]) {
$rootScope.$broadcast('keydown-' + name, angular.element(e.target))
}
}
})
});
这允许它在加载任何控制器之前执行。
然后在您的控制器中,您应该执行“安全”$ scope。$ apply方法检查现有摘要或应用阶段,如果有,那么我们不应该运行$scope.$apply
。另外我们可以。
// Again make sure that you have everything you need injected properly.
// I need $rootScope injected so I can check the broadcast
app.controller('MainCtrl', ['$scope', '$rootScope', function ($scope, $rootScope) {
$scope.hello = "Hello World";
var count = 0;
$scope.hideOverlays = function () {
count++;
$scope.safeApply(function () {
$scope.hello = "You pressed the escape key " + count + " times.";
});
};
$rootScope.$on('keydown-escape', $scope.hideOverlays);
$scope.safeApply = function (fn) {
var phase = this.$root.$$phase;
// If AngularJS is currently in the digest or apply phase
// we will just invoke the function passed in
if (phase == '$apply' || phase == '$digest') {
// Let's check to make sure a function was passed
if (fn && (typeof (fn) === 'function')) {
// Invoke the function passed in
fn();
}
} else {
// If there is no apply or digest in the phase
// we will just call $scope.$apply
this.$apply(fn);
}
};
}]);
Here is a working fiddle showing DOM updates when the escape key is pressed