0

このような上/下キーに応答する小さなイベントハンドラーがあります...

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

};
4

1 に答える 1

0

したがって、Angular でエラーを発生させずにこれを処理する方法があります。基本的に、Angular は実行されるたびにこの変更を取得します$digest。ここでの問題は、changeIndexメソッドがトリガーされていないため、手動で$digest呼び出す必要があることです。$apply

ただし、アプリが起動すると、まだ実行中にchangeIndexメソッドが呼び出され、への別の呼び出し内で$digestへの呼び出しを行うことができないため、エラーがトリガーされます。$digest$digest

$digestAngular は、現在実行中かどうかを判断する方法を提供しているため、 への呼び出しは次の$applyように処理する必要があります...

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

true の場合$$phase、angular は現在実行中$digestであり、変更は自動的に取得されます。$$phaseが false の場合は、$apply手動でトリガーする必要があります。

これは修正ですが、 $apply を手動で呼び出す必要はありません。手動の参照カウントに少し似ていて、このように機能するメソッドが私には面白いにおいがします。

于 2013-09-08T11:04:35.970 に答える