ste*_*alz 38 javascript angularjs angularjs-directive angularjs-ng-click
我正在寻找使用AngularJS的单击和双击事件处理,因为即使为我们的元素设置了ng-dblclick指令,AngularJS也总是仅触发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.
* ...
*/
};
}
Run Code Online (Sandbox Code Playgroud)
HTML:
<div ng-controller="MyController">
<a href="#" ng-click="singleClickAction()">CLICK</a>
</div>
Run Code Online (Sandbox Code Playgroud)
所以我的问题是(因为我是一个AngularJS新手):有人可以更有经验地写一些很好的指令来处理这两个事件吗?
在我看来,完美的方法是改变ng-click,ng-dblclick的行为,并添加一些"ng-sglclick"指令来处理单击式代码.不知道它是否可能,但我发现它对每个人都非常有用.
随意分享您的意见!
Rob*_*Rob 28
你可以写自己的.我看了一下如何处理角点击并使用我在这里找到的代码修改它:Jquery绑定双击并单击单击
<div sglclick="singleClick()" ng-dblClick="doubleClick()" style="height:200px;width:200px;background-color:black">
mainMod.controller('AppCntrl', ['$scope', function ($scope) {
$scope.singleClick = function() {
alert('Single Click');
}
$scope.doubleClick = function() {
alert('Double Click');
}
}])
mainMod.directive('sglclick', ['$parse', function($parse) {
return {
restrict: 'A',
link: function(scope, element, attr) {
var fn = $parse(attr['sglclick']);
var delay = 300, clicks = 0, timer = null;
element.on('click', function (event) {
clicks++; //count clicks
if(clicks === 1) {
timer = setTimeout(function() {
scope.$apply(function () {
fn(scope, { $event: event });
});
clicks = 0; //after action performed, reset counter
}, delay);
} else {
clearTimeout(timer); //prevent single-click action
clicks = 0; //after action performed, reset counter
}
});
}
};
}])
Run Code Online (Sandbox Code Playgroud)
这是一个例子
sti*_*tes 25
格雷格的答案绝对是最贴心的答案.我将以他的答案为基础,提出一个不需要编写新代码的版本,并且不需要在控制器中使用新的注入.
首先要问的是为什么超时会被用来解决这些问题.本质上,它们用于使函数跳过当前事件循环的其余部分,以便执行是干净的.但是,在角度中,您实际上对摘要循环的工作原理感兴趣.它与您的经典事件处理程序几乎相同,除了一些微小的差异,这使得它非常适合用户体验.你手头上有更动功能的执行顺序的一些工具包括scope.$eval,scope.$evalAsync,scope.$apply,和scope.$applyAsync.
我相信$applys会启动另一个消化循环,离开$evals.$eval将使用当前上下文立即运行您包含的任何代码$scope,$evalAsync并将您的函数排入队列以在摘要循环结束时运行.从本质上讲,$evalAsync是一个更清晰的版本,$timeout有一个很大的区别 - 第一个有上下文,存在于范围内!
这意味着你可以,实际上,处理ng-click并ng-dblclick在相同的元素.但请注意,这仍然会在双击功能之前触发单击功能.这应该足够了:
<div ng-controller="MyController">
<a href="#"
ng-click="$evalAsync(singleClickAction())"
ng-dblclick="doubleClickAction()">
CLICK
</a>
</div>
Run Code Online (Sandbox Code Playgroud)
这是使用Angular 1.6.4的预期功能的jsfiddle.
Gre*_*ter 13
遇到这个并认为我会抛弃另一种选择.除了两个关键点之外,它与原始海报没有什么不同.
1)没有嵌套的函数声明.
2)我使用$ timeout.我经常使用$ timeout,即使没有延迟......特别是如果我开始承诺做其他工作.当摘要周期到来时,$ timeout将触发,这将确保应用范围内的任何数据更改.
特定
<img src="myImage.jpg" ng-click="singleClick()" ng-dblclick="doubleClick()">
Run Code Online (Sandbox Code Playgroud)
在您的控制器中,singleClick函数将如下所示:
$scope.singleClick = function () {
if ($scope.clicked) {
$scope.cancelClick = true;
return;
}
$scope.clicked = true;
$timeout(function () {
if ($scope.cancelClick) {
$scope.cancelClick = false;
$scope.clicked = false;
return;
}
//do something with your single click here
//clean up
$scope.cancelClick = false;
$scope.clicked = false;
}, 500);
};
Run Code Online (Sandbox Code Playgroud)
而doubleClick函数看起来很正常:
$scope.doubleClick = function () {
$timeout(function () {
//do something with your double click here
});
};
Run Code Online (Sandbox Code Playgroud)
希望这有助于某人......