Javascript 使用AngularJS在同一元素上处理ng click和ng dblclick
我一直在寻找AngularJS的单点和双击事件处理,因为AngularJS总是只触发ng click事件,即使我们的元素设置了ng dblclick指令 以下是一些适用于寻求解决方案的人的工作代码: JS: HTML:Javascript 使用AngularJS在同一元素上处理ng click和ng dblclick,javascript,angularjs,angularjs-directive,angularjs-ng-click,Javascript,Angularjs,Angularjs Directive,Angularjs Ng Click,我一直在寻找AngularJS的单点和双击事件处理,因为AngularJS总是只触发ng click事件,即使我们的元素设置了ng dblclick指令 以下是一些适用于寻求解决方案的人的工作代码: JS: HTML: 所以我的问题是(因为我是AngularJS的新手):有没有经验更丰富的人能为处理这两个事件写一些好的指令 在我看来,最好的方法是改变ng click、ng dblclick的行为,并添加一些“ng sglclick”指令来处理仅单击的代码。 我不知道这是否可能,但我会发现它对
所以我的问题是(因为我是AngularJS的新手):有没有经验更丰富的人能为处理这两个事件写一些好的指令
在我看来,最好的方法是改变ng click、ng dblclick的行为,并添加一些“ng sglclick”指令来处理仅单击的代码。
我不知道这是否可能,但我会发现它对每个人都非常有用
请随意分享您的意见 你可以自己写。我查看了angular如何处理click,并使用我在此处找到的代码对其进行了修改:
mainMod.controller('AppCntrl',['$scope',函数($scope){
$scope.singleClick=function(){
警报(“单击”);
}
$scope.doubleClick=function(){
警报(“双击”);
}
}])
mainMod.directive('sglclick',['$parse',function($parse){
返回{
限制:“A”,
链接:功能(范围、元素、属性){
var fn=$parse(attr['sglclick']);
var延迟=300,点击次数=0,定时器=null;
元素上('click',函数(事件){
点击次数+++;//点击次数
如果(单击===1){
计时器=设置超时(函数(){
作用域:$apply(函数(){
fn(作用域,{$event:event});
});
单击=0;//执行操作后,重置计数器
},延误);
}否则{
clearTimeout(计时器);//防止单击操作
单击=0;//执行操作后,重置计数器
}
});
}
};
}])
这里有一个例子
我在试图找到处理双击和同时单击的方法时遇到了一个问题。我用这里的概念取消了最初的点击。如果在延迟之前发生第二次单击,则执行双击操作。如果没有第二次单击,延迟结束后,将运行默认的ngClick操作,并在元素上触发原始事件(并允许像最初一样冒泡) 范例
<div ng-click="singleClick()"><span double-click="doubleClick()">double click me</span></div>
遇到这个,我想我会放弃另一个选择。除了两个关键点外,它与原始海报没有太大区别 1) 没有嵌套的函数声明 2) 我使用$timeout。我经常使用$timeout,即使没有延迟……特别是当我开始承诺做其他工作时。$timeout将在摘要周期结束时触发,以确保对作用域的任何数据更改都得到应用 给定 双击功能将看起来正常:
$scope.doubleClick = function () {
$timeout(function () {
//do something with your double click here
});
};
希望这对某人有所帮助。格雷格的答案绝对是最简洁的答案。我将在他的答案的基础上提出一个版本,在这个版本中,不需要编写新的代码,也不需要在控制器中使用新的注入 首先要问的是,为什么要用超时来解决这类问题。从本质上讲,它们用于使函数跳过当前事件循环的其余部分,以便执行干净。然而,在angular中,您实际上对摘要循环的工作方式感兴趣。它几乎与您的经典事件处理程序相同,只是有一些细微的差异,这使它非常适合UX。您手头上的一些用来扰乱函数执行顺序的工具包括
scope.$eval
,scope.$evalAsync
,scope.$apply
和scope.$applyAsync
我相信$apply
s将启动另一个摘要循环,剩下$eval
s$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>
.如果在
双击
上调用单点
,不会出现任何错误,那么它也可以工作
<div
onclick="var scope = angular.element(this).scope(); scope.singleClick();"
ng-click="null"
ng-dblclick="doubleClick()"
></div>
在此处连接答案:
- 为简单起见使用
- 创建一个
,如@Rob(此线程中被接受为最佳答案的指令)指令
- 通过使用替换
build-in指令,解决@Rob-answer问题ngClick
ng dblclick
,则不应阻止单次单击(此处是实现此想法的)
(函数(角度){
"严格使用",;
var myApp=angular.module('myApp',[]);
控制器('myCtrl',['$scope',函数($scope){
$scope.click=false;
$scope.singleClick=function(){
$scope.click='single';
};
$scope.doubleClick=function(){
$scope.click='double';
};
}]);
//删除buildin ng,单击以解决问题https://stackoverflow.com/a/20445344/4352306
myApp.config(函数($provide){//来源:https://stackoverflow.com/a/23209542/4352306
$provide.decorator('ngClickDirective',['$delegate',函数($delegate){
//$delegate是所有ng clic的数组
.directive('doubleClick', function($timeout, _) {
var CLICK_DELAY = 300
var $ = angular.element
return {
priority: 1, // run before event directives
restrict: 'A',
link: function(scope, element, attrs) {
var clickCount = 0
var clickTimeout
function doubleClick(e) {
e.preventDefault()
e.stopImmediatePropagation()
$timeout.cancel(clickTimeout)
clickCount = 0
scope.$apply(function() { scope.$eval(attrs.doubleClick) })
}
function singleClick(clonedEvent) {
clickCount = 0
if (attrs.ngClick) scope.$apply(function() { scope.$eval(attrs.ngClick) })
if (clonedEvent) element.trigger(clonedEvent)
}
function delaySingleClick(e) {
var clonedEvent = $.Event('click', e)
clonedEvent._delayedSingleClick = true
e.preventDefault()
e.stopImmediatePropagation()
clickTimeout = $timeout(singleClick.bind(null, clonedEvent), CLICK_DELAY)
}
element.bind('click', function(e) {
if (e._delayedSingleClick) return
if (clickCount++) doubleClick(e)
else delaySingleClick(e)
})
}
}
})
<img src="myImage.jpg" ng-click="singleClick()" ng-dblclick="doubleClick()">
$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);
};
$scope.doubleClick = function () {
$timeout(function () {
//do something with your double click here
});
};
<div ng-controller="MyController">
<a href="#"
ng-click="$evalAsync(singleClickAction())"
ng-dblclick="doubleClickAction()">
CLICK
</a>
</div>
<div
onclick="var scope = angular.element(this).scope(); scope.singleClick();"
ng-click="null"
ng-dblclick="doubleClick()"
></div>