想知道我将如何实现“除此元素之外的任何地方都点击”事件。
我有一些东西可以与文件资源管理器中的文件列表进行比较。您可以选择某些元素,但如果您在元素控制器外部单击,则需要取消选择所有内容。
添加了屏幕截图以使其更清晰。所以我想要做的是,如果我点击除语言元素之外的任何地方,它应该触发一个事件。
更新
澄清一下,我不是在问如何用 jQuery 做到这一点。
想知道我将如何实现“除此元素之外的任何地方都点击”事件。
我有一些东西可以与文件资源管理器中的文件列表进行比较。您可以选择某些元素,但如果您在元素控制器外部单击,则需要取消选择所有内容。
添加了屏幕截图以使其更清晰。所以我想要做的是,如果我点击除语言元素之外的任何地方,它应该触发一个事件。
更新
澄清一下,我不是在问如何用 jQuery 做到这一点。
*另外:标记社区维基(我没有积分)因为错误
N 调用该指令的 N 次使用。对于具有匹配表达式的同一范围内的使用,这可能是不可取的。
没有任何东西会破坏事件处理程序!!!!坏的!坏的!坏的!
所以,我正在更新这个答案。希望它没有给任何人带来太多麻烦。
这是一个修复了这些问题的新 plunker ……个别应用程序开发人员可能会遇到其他问题。这只是如何处理此问题的示例。
app.factory('clickAnywhereButHereService', function($document){
var tracker = [];
return function($scope, expr) {
var i, t, len;
for(i = 0, len = tracker.length; i < len; i++) {
t = tracker[i];
if(t.expr === expr && t.scope === $scope) {
return t;
}
}
var handler = function() {
$scope.$apply(expr);
};
$document.on('click', handler);
// IMPORTANT! Tear down this event handler when the scope is destroyed.
$scope.$on('$destroy', function(){
$document.off('click', handler);
});
t = { scope: $scope, expr: expr };
tracker.push(t);
return t;
};
});
app.directive('clickAnywhereButHere', function($document, clickAnywhereButHereService){
return {
restrict: 'A',
link: function(scope, elem, attr, ctrl) {
var handler = function(e) {
e.stopPropagation();
};
elem.on('click', handler);
scope.$on('$destroy', function(){
elem.off('click', handler);
});
clickAnywhereButHereService(scope, attr.clickAnywhereButHere);
}
};
});
你已经找到了你找到的一个答案,但我已经为你整理了一个 plunk来告诉你它缺少什么。
app.directive('clickAnywhereButHere', function($document){
return {
restrict: 'A',
link: function(scope, elem, attr, ctrl) {
var elemClickHandler = function(e) {
e.stopPropagation();
};
var docClickHandler = function() {
scope.$apply(attr.clickAnywhereButHere);
};
elem.on('click', elemClickHandler);
$document.on('click', docClickHandler);
// teardown the event handlers when the scope is destroyed.
scope.$on('$destroy', function() {
elem.off('click', elemClickHandler);
$document.off('click', docClickHandler);
});
}
}
})
HTML
<a click-anywhere-but-here="clickedSomewhereElse()"
ng-click="clickedHere()">Don't Click Me!</a>
当前接受的答案的问题是,如果您多次使用该指令,则附加了该指令的每个 DOM 元素都将防止冒泡(因此,如果您将它放在两个元素上,并且单击其中一个,则两者的回调都将是阻止)。
编辑 - 避免使用 jQuery,清理- 在您的范围内定义一个函数,并将其直接传递给该指令(不带括号),事件将在调用时传递给它。
app.directive('clickAnywhereButHere', function($document, $parse) {
return {
restrict: 'A',
scope: {
callback : '=clickAnywhereButHere'
},
link: function(scope, element, attr, ctrl) {
var handler = function(event) {
if (!element[0].contains(event.target)) {
scope.callback(event);
}
};
$document.on('click', handler);
scope.$on('$destroy', function() {
$document.off('click', handler);
});
}
}
});
在 HTML 中的使用
<a click-anywhere-but-here="myFunction"></a>
在控制器中的使用
$scope.myFunction = function (event) { ... }
——
请注意,您可能需要scope.callback(event)
用scope.$apply()
如果您有很多需要此指令的元素,这里是另一个性能优化的解决方案。(例如一个包含 100 多行的列表,每行都有这个指令)
这将始终只包含一个 $document 侦听器
angular.module('app').directive('clickElsewhere', ['$document', function ($document) {
return {
link: function postLink(scope, element, attr) {
var elsewhere = true;
element.on('click', function(e) {
elsewhere = false;
$document.off('click', clickElsewhere);
$document.on('click', clickElsewhere);
});
var clickElsewhere = function() {
if (elsewhere) {
scope.$apply(attr.clickElsewhere);
$document.off('click', clickElsewhere);
}
elsewhere = true;
};
}
};
}]);
Max Bates 解决方案的问题是所有指令都为 $document.on('click', function(...)); 添加了一个侦听器。导致性能问题的事件。
Max Bates 已经说明了接受答案的问题。
在这篇博文上找到了答案。
指示:
app.directive('documentClick', function ($document, $parse) {
var linkFunction = function ($scope, $element, $attributes) {
var scopeExpression = $attributes.documentClick;
var invoker = $parse(scopeExpression);
$document.on('click', function (event) {
$scope.$apply(function () {
invoker($scope, { $event: event });
});
});
};
return linkFunction;
});
控制器:
app.controller('PageCtrl', function ($scope) {
$scope.click = function (e) {
if (!$(e.target).is('.language')) {
//do stuff
}
};
});
看法:
<body ng-controller='PageCtrl' document-click='click($event)'></body>
这是一个基于 Max 解决方案的变体,但在标准角度事件指令方面更自然:
app.directive('clickOut', function($document) {
return {
restrict: 'A',
scope: {
clickOut: '&'
},
link: function (scope, element) {
var handler = function(event) {
if (!element[0].contains(event.target)) {
scope.$apply(function () {
scope.clickOut({ $event : event });
});
}
};
$document.on('click', handler);
scope.$on('$destroy', function() {
$document.off('click', handler);
});
}
};
});
用法
<div click-out="myFunction()"></div>
传递点击事件
<div click-out="myFunction($event)"></div>