javascript - Angular $scope 变量在通过 $rootScope.$on 调用后未更新

标签 javascript angularjs

我有一个全局方法来监视整个应用程序中的按键操作。当按键发生时,我会像这样广播该事件:

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))
        }
    }
})

这一切都运行良好。在我的 Controller 中,我像这样监听事件:

$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;
        }
    }

当我从 Controller 内部调用这个方法时,一切都工作正常,所以我想知道 Angular 是否根据方法的调用方式做了不同的事情。我尝试过调用 $scope.$apply()。除了看起来这不是正确的做法之外,我还收到一个错误,所以那里没有骰子。非常感谢任何帮助!

最佳答案

有很多缺失的代码会带来一些问题,例如,您在哪里执行 keydown 事件,在我的示例中,您会看到我已将其放在 中Angular 中的 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))
            }
        }
    })
});

这允许它在加载任何 Controller 之前执行。

<小时/>

然后在你的 Controller 中,你应该执行一个“安全”的 $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

关于javascript - Angular $scope 变量在通过 $rootScope.$on 调用后未更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33019786/

相关文章:

javascript - 如何从 asp.net 中的代码隐藏访问 JavaScript 变量

javascript - 使用 Node js、AngularJs 和 JWT 使用用户名和密码进行身份验证

javascript获取对象中的值

javascript - jQuery 隐藏一组与索引不匹配的容器

javascript - 在不同的 div 和类中交换相同的文本

javascript - Egghead.io webpack Angular 教程

javascript - sequelize, 语句(where) in statement(where)

angularjs - Meteor、Laravel RESTful API + AngularJS 或 Laravel 用于我的下一个 Web 应用程序

angularjs - 使用 AngularJS 从选择选项中删除空白选项

javascript - SVG 文件中的图像(jpeg 和 png)文件是如何格式化的?