如何在不使用Angular.js中的$ apply()的情况下编写此函数

时间:2013-09-03 09:51:50

标签: javascript angularjs

我有一个小事件处理器响应这样的上/下键......

    $scope.$on('handleDownKey', function(){ changeIndex(1) });
    $scope.$on('handleUpKey', function(){ changeIndex(-1) });

    function changeIndex(val){
        $scope.listIndex += val;
        //$scope.$apply();
    }

在我看来,我有一个看起来有点像这样的列表

<li ng-class="{selected: listIndex == $index}" ng-repeat="item in items">
    <p>{{item.title}}</p>
    <p>{{item.desc}}</p>
</li>

我遇到的问题是listIndex的更改只会在我取消注释$scope.apply()行时反映在视图中。

但是当我取消注释该行时,我会在应用程序加载时收到Error: $digest already in progress消息。

我的猜测是我不是以Angular的方式做这个,但是如何用Angular编写这样的例子?

对于那些想知道handleKeyDown来自哪里的人,我有一个指令,它接受键盘事件并将它们传递给名为KeyboardSrv的服务。该指令看起来像这样......

myModule.directive('onKeydown', function(KeyboardSrv) {
    return function(scope, elm, attrs) {
        function applyKeydown() {
          scope.$apply(attrs.onKeydown);
        };           

        elm.bind('keydown', function(evt) {
            KeyboardSrv.prepareEvent(evt)
        });
    };
});

服务看起来像这样......

function KeyboardSrv($rootScope){

    var KeyboardSrv = {};       
    KeyboardSrv.code;
    KeyboardSrv.evt;

    KeyboardSrv.prepareEvent = function(evt){
        KeyboardSrv.code = evt.which;
        KeyboardSrv.evt = evt;

        if(KeyboardSrv.code == 40){
            KeyboardSrv.broadcastEvent("handleDownKey", evt);
        }

        if(KeyboardSrv.code == 38){
            KeyboardSrv.broadcastEvent("handleUpKey", evt);
        }

    }

    KeyboardSrv.broadcastEvent = function(msg, event){
        $rootScope.$broadcast(msg, event);
    }

    return KeyboardSrv;

};

1 个答案:

答案 0 :(得分:0)

因此有一种方法可以在Angular中处理此问题而不会触发错误。基本上,只要角度运行$digest,它就会获得此更改。我在这里遇到的问题是我的changeIndex方法未触发$digest,因此我必须手动调用$apply

但是,当应用启动时,会调用changeIndex方法,而$digest仍在运行,这会触发错误,因为您无法在另一个内部调用$digest致电$digest

Angular确实提供了一种方法来告诉当前正在运行的$digest,因此应该像这样处理对$apply的调用......

$scope.listIndex += val
if(!$$phase) $scope.$apply();

如果$$phase为真,则当前角度为$digest,我们的更改将自动获取。如果$$phase为false,则我们需要手动触发$apply

虽然这是一个修复,但我仍然宁愿不必手动调用$ apply。它感觉有点太像手动引用计数,并且使用这种方式工作的方法对我来说闻起来很有趣。