使用 AngularJS 在同一元素上处理 ng-click 和 ng-dblclick [英] Handling ng-click and ng-dblclick on the same element with AngularJS

查看:31
本文介绍了使用 AngularJS 在同一元素上处理 ng-click 和 ng-dblclick的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在寻找 AngularJS 的单击和双击事件处理,因为即使为我们的元素设置了 ng-dblclick 指令,AngularJS 也总是只触发 ng-click 事件.

这里是一些寻求解决方案的人的工作代码:

JS:

function MyController($scope) {var waitingForSecondClick = false;$scope.singleClickAction = function() {执行DoubleClick = false;如果(waitingForSecondClick){waitingForSecondClick = false;执行DoubleClick = true;返回 $scope.doubleClickAction();}waitingForSecondClick = true;设置超时(函数(){waitingForSecondClick = false;返回 singleClickOnlyAction();}, 250);//延迟/** 用单击和双击执行的代码放在这里.* ...*/var singleClickOnlyAction = function() {如果(执行DoubleClick)返回;/** 仅通过单击执行的代码到这里.* ...*/}}$scope.doubleClickAction = function() {/** 仅通过双击执行的代码到这里.* ...*/};}

HTML:

<a href="#" ng-click="singleClickAction()">点击</a>

所以我的问题是(因为我是一个 AngularJS 新手):有没有更有经验的人可以写一些很好的指令来处理这两个事件?

在我看来,最好的方法是更改​​ ng-click、ng-dblclick 的行为并添加一些ng-sglclick"指令来处理仅单击代码.不知道它是否可能,但我发现它对每个人都非常有用.

随时分享您的意见!

解决方案

Greg 的答案绝对是最接近最简洁的答案.我将根据他的回答提出一个不需要编写新代码并且不需要在控制器中使用新注入的版本.

首先要质疑的是为什么要使用超时来解决此类问题.本质上,它们用于使函数跳过当前事件循环的其余部分,以便执行干净.然而,在 angular 中,您实际上对摘要循环的工作方式感兴趣.它与您的经典事件处理程序几乎相同,除了一些使其非常适合 UX 的细微差别.您手头上用来处理函数执行顺序的一些工具包括 scope.$evalscope.$evalAsyncscope.$applyscope.$applyAsync.

我相信 $apply 将启动另一个摘要循环,从而留下 $eval .$eval 将立即运行您在当前 $scope 的上下文中包含的任何代码,并且 $evalAsync 将您的函数排队以在摘要循环结束.从本质上讲,$evalAsync$timeout 的一个更简洁的版本,有一个很大的不同 - 第一个有上下文并且存在于作用域中!

这意味着您实际上可以在同一个元素上处理 ng-clickng-dblclick.但是请注意,这仍然会在双击功能之前触发单击功能.这应该足够了:

<a href="#"ng-click="$evalAsync(singleClickAction())"ng-dblclick="doubleClickAction()">点击</a>

这是一个使用 Angular 1.6.4 实现预期功能的 jsfiddle.

I was looking for both single and double-click event handling with AngularJS, since AngularJS always fires only the ng-click event even if there is ng-dblclick directive set for our element.

Here is some working code for those who seek solution:

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>

So my question is (since I'm an AngularJS newbie): could somebody more experianced write some nice directive for handling those both events?

In my opinion the perfect way would be to change the behaviour of ng-click, ng-dblclick and add some "ng-sglclick" directive for handling single-click-only code. Don't know if it is even possible, but I'd find it very useful for everyone.

Feel free to share your opinions!

解决方案

Greg's answer is definitely closest to the cleanest answer. I'm going to build on his answer to come up with a version where no new code needs to be written, and no new injections need to be used in your controller.

The first thing to question is why timeouts are used to hack around these kinds of problems. Essentially, they're used to make a function skip the rest of the current event loop so that the execution is clean. In angular, however, you are actually interested in how the digest loop works. It's almost the same as your classic event handler, except for some minor differences which make it great for UX. Some tools that you have on hand to mess around with the order of function execution include scope.$eval, scope.$evalAsync,scope.$apply, and scope.$applyAsync.

I believe the $applys will kick off another digest loop, which leaves the $evals. $eval will run whatever code you include immediately with the context of the current $scope and $evalAsync will queue your function to be run at the end of the digest loop. Essentially, $evalAsync is a cleaner version of $timeout with one big difference — the first has context and exists on the scope!

This means that you can, actually, handle ng-click and ng-dblclick on the same element. Note, however, that this will still trigger the single-click function before the double-click function. This should be sufficient:

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

Here's a jsfiddle with the intended functionality using Angular 1.6.4.

这篇关于使用 AngularJS 在同一元素上处理 ng-click 和 ng-dblclick的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆