如果不在Angular.js中使用$apply(),我该如何编写此函数

How can I write this function without using $apply() in Angular.js

本文关键字:函数 何编写 apply js Angular 如果不      更新时间:2023-09-26

我有一个小事件处理程序来响应像这样的向上/向下键。。。

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

因此,有一种方法可以在Angular中处理此问题而不会触发错误。基本上,无论何时运行$digest,angular都会接收到这种变化。这里的问题是我的changeIndex方法没有触发$digest,所以我必须手动调用$apply

然而,当应用程序启动时,会调用changeIndex方法,而$digest仍在运行,这会触发一个错误,因为在对$digest的另一个调用中无法调用$digest

Angular确实提供了一种方法来判断$digest当前是否正在运行,因此对$apply的调用应该这样处理。。。

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

如果$$phase为真,则angular当前正在运行$digest,并且我们的更改将自动获得。如果$$phase为false,则需要手动触发$apply

虽然这是一个修复程序,但我仍然希望不必手动调用$apply。这感觉有点太像手动参考计数了,而且用这种方式工作的方法闻起来很有趣。