1. ホーム
  2. javascript

[解決済み] AngularJSで同じ要素にng-clickとng-dblclickを処理する

2022-02-15 19:33:51

質問

AngularJSでは、要素にng-dblclickディレクティブが設定されていても、常にng-clickイベントのみが発生するため、シングルクリックとダブルクリックの両方のイベント処理を行いたいと考えていました。

以下は、解決策を求める人のために、いくつかの動作するコードです。

JSです。

function MyController($scope) {

    var waitingForSecondClick = false;
    $scope.singleClickAction = function() {

        executingDoubleClick = false;
        if (waitingForSecondClick) {
            waitingForSecondClick = false;
            executingDoubleClick = true;
            return $scope.doubleClickAction();
        }
        waitingForSecondClick = true;

        setTimeout(function() {
            waitingForSecondClick = false;
            return singleClickOnlyAction();
        }, 250); // delay

        /*
         * Code executed with single AND double-click goes here.
         * ...
         */

        var singleClickOnlyAction = function() {
            if (executingDoubleClick) return;

            /*
             * Code executed ONLY with single-click goes here.
             * ...
             */

        }

    }

    $scope.doubleClickAction = function() {

        /*
         * Code executed ONLY with double-click goes here.
         * ...
         */

    };

}

HTMLです。

<div ng-controller="MyController">
    <a href="#" ng-click="singleClickAction()">CLICK</a>
</div>

そこで質問なのですが(私はAngularJSの初心者なので)、誰かもっと経験豊富な人が、この2つのイベントを処理するための素敵なディレクティブを書いてくれないでしょうか?

私の意見では、完璧な方法は、ng-click、ng-dblclickの動作を変更し、シングルクリックのみのコードを処理するためのいくつかの"ng-sglclick"ディレクティブを追加することです。 それが可能かどうかは分かりませんが、誰にとっても非常に便利だと思います。

ご意見をお聞かせください。

解決方法は?

Gregの回答が最もクリーンな答えに近いのは間違いないでしょう。私は彼の答えに基づいて、新しいコードを書く必要がなく、コントローラで新しいインジェクションを使用する必要がないバージョンを考え出すつもりです。

まず疑問に思うのは、この種の問題を回避するために、なぜタイムアウトが使われるのかということです。基本的には、関数が現在のイベントループの残りをスキップして、実行をクリーンにするために使用されます。しかし、angularでは、実際にダイジェストループがどのように動作するかに興味があるはずです。これは古典的なイベントハンドラとほとんど同じですが、いくつかの小さな違いがあるため、UXに最適なものとなっています。関数の実行順序を変更するためのツールには、次のようなものがあります。 scope.$eval , scope.$evalAsync , scope.$apply となります。 scope.$applyAsync .

の方がいいと思います。 $apply は別のダイジェストループをキックオフし、その結果 $eval s. $eval は、あなたがインクルードしたコードを、現在の $scope$evalAsync を実行すると、関数がダイジェストループの最後で実行されるようキューに入れられます。基本的には $evalAsync は、よりクリーンなバージョンの $timeout 最初のものはコンテキストを持ち、スコープ上に存在するのです。

これはつまり、実際に ng-clickng-dblclick を同じ要素で使用することができます。 ただし、この場合でも、ダブルクリック機能の前にシングルクリック機能が起動することに注意してください。 . これで十分でしょう。

<div ng-controller="MyController">
    <a href="#"
       ng-click="$evalAsync(singleClickAction())"
       ng-dblclick="doubleClickAction()">
       CLICK
    </a>
</div>

Angular 1.6.4を使って意図した機能を実現したjsfiddleを以下に示します。 .