如何在Angular中有效地检测元素点击
How to detect element click efficiently in Angular?
这是我的指令的链接函数
function linkFunc(scope, element, attr){
// Detect Element Click Logic
scope.myCtrl.clickedElsewhere = {value: true};
$document.on('click', function(){
scope.myCtrl.clickedElsewhere.value = true;
scope.$apply();
});
element.on('click', function(){
event.stopPropagation();
scope.myCtrl.clickedElsewhere.value = false;
scope.$apply();
});
// End Detect Element Click Logic
}
正如我们所看到的,我们使用了$document.on()
和scope.apply
,这意味着每次点击文档中的任何位置,我们都会触发一个摘要循环。如果我们有很多$watch
触发器,这可能会导致网页速度减慢。尽管这种实现并不完全有效,但我想不出其他方法来检测元素上的点击和元素外的点击,以扩展和收缩我的元素。
有人能提供一些见解吗?
感谢
在文档点击处理程序中调用$apply()
之前检查scope.myCtrl.clickedElsewhere.value
会更有效率
$document.on('click', function(){
if(!scope.myCtrl.clickedElsewhere.value){
scope.myCtrl.clickedElsewhere.value = true;
scope.$apply();
}
});
当状态没有变化时,这将防止不必要的消化。
你也可以删除这个点击监听器,并在点击元素时重新应用它:
function docHandler() {
if (!scope.myCtrl.clickedElsewhere.value) {
scope.myCtrl.clickedElsewhere.value = true;
scope.$apply();
$document.off('click');//remove event listener completely
}
}
element.on('click', function() {
event.stopPropagation();
scope.myCtrl.clickedElsewhere.value = false;
scope.$apply();
$document.on('click', docHandler);// add document listener
});
您只需创建一个点击关闭指令
myApp.directive('clickOff', function($parse, $document) {
var dir = {
compile: function($element, attr) {
// Parse the expression to be executed
// whenever someone clicks _off_ this element.
var fn = $parse(attr["clickOff"]);
return function(scope, element, attr) {
// add a click handler to the element that
// stops the event propagation.
element.bind("click", function(event) {
event.stopPropagation();
});
angular.element($document[0].body).bind("click",function(event) {
scope.$apply(function() {
fn(scope, {$event:event});
});
});
};
}
};
return dir;
});
用法:
<div ng-app="myApp">
<button ng-click="show=true;" click-off="show=false;">
Click Me
</button>
<div class="message" ng-show="show" ng-init="show = false">
You clicked on the button. Now click anywhere else...
</div>
</div>
示例:https://jsfiddle.net/oytdwyxj/
您可以创建两个指令,它们之间具有父/子关系。
看看我创建的手风琴指令,我相信这就是你需要的,以了解你的情况。
指令:
app.directive("accordion", function () {
return {
template: "<div ng-transclude></div>",
restrict: "E",
scope: {
closeall: "@"
},
transclude: true,
replace: true,
controller: function ($scope, $element, $attrs) {
var itensScope = [];
var addItemScope = function (scope) {
itensScope.push(scope);
};
var closeItens = function () {
if ($scope.closeall == "false") return;
angular.forEach(itensScope, function (scope) {
scope.showItem = false;
});
}
return {
addItemScope: addItemScope,
closeItens: closeItens
};
}
};
});
app.directive("accordionItem", function () {
return {
template: "<div><div class='item' ng-class='{itemClose: !showItem}'>{{title}}</div><div class='itemInformation' ng-show='showItem' ng-transclude></div></div>",
restrict: "E",
transclude: true,
replace: true,
scope: {
title: "@"
},
require: "^accordion",
link: function (scope, element, attrs, ctrl, transcludeFn) {
ctrl.addItemScope(scope);
element.bind("click", function () {
ctrl.closeItens();
scope.$apply(function () {
scope.showItem = !scope.showItem;
});
});
}
};
});
用法:
<accordion closeall="true">
<accordion-item title="A">
<p>
A
</p>
</accordion-item>
<accordion-item title="B">
<p>
B
</p>
</accordion-item>
</accordion>
我不久前创建了这个例子,它在我的GitHub中可用:https://github.com/rodrigobranas/branas-angular-ui
相关文章:
- 在幻灯片放映时检测元素具有特定类
- Javascript检测元素前面的元素
- 使用jquery.visible.js和偏移量检测元素是否在视口中
- 滚动后,检测元素何时返回到原始位置
- 无法按类名检测元素
- 如何在Angular中有效地检测元素点击
- 如何使用 jQuery 检测元素的顶部靠近浏览器底部
- 我需要一种新的方法来检测元素 HTML 是否有更改
- 我们如何检测元素外部的双击
- JavaScript中有没有办法检测元素是否附加了任何事件
- 检测元素高度变化,如果太小则隐藏
- 如何检测元素在跨域父级的iframe中是否可见
- jQueryUI-检测元素是否被拖动
- 使用JavaScript检测元素外部的点击
- JQuery:检测元素和所有子元素何时加载
- 在没有JQuery的情况下激发此不可检测元素的.click()事件
- 如何检测元素外部的点击,但该元素有子元素
- 检测元素是否已通过javascript调整大小
- 如何检测元素外部的触摸端事件
- 检测元素外的子对象何时获得焦点