[英]Add and remove event listener when element receives and loses a class
I have a small search button which expands and displays an input once user clicks on a magnifying glass icon.我有一个小的搜索按钮,一旦用户点击放大镜图标,它就会展开并显示输入。 At this point I am giving my search element the .active
class.在这一点上,我给我的搜索元素.active
类。 Once a user starts typing, a 'modal' window is shown with results of the search.一旦用户开始输入,就会显示一个带有搜索结果的“模态”窗口。 What I want to be able to do is add and remove my event listener on an outside click (anywhere else apart from the modal window, search button and the input).我想要做的是在外部单击时添加和删除我的事件侦听器(除了模态窗口、搜索按钮和输入之外的任何其他地方)。
Just to clarify all of the above is within the search element so they're all children elements of search.只是为了澄清以上所有内容都在搜索元素中,因此它们都是搜索的子元素。
I have managed to remove the event listener when the element is removed from the DOM but I can't do it so that it is added and removed when the elements receives and loses the .active
class.当元素从 DOM 中删除时,我设法删除了事件侦听器,但我无法这样做,以便在元素接收和丢失.active
类时添加和删除它。 How can I possibly do that?我怎么可能这样做?
My directive looks as follows.我的指令如下所示。
outsideSearchClick.$inject = ['$document'];
function outsideSearchClick($document) {
return {
scope: {
outsideSearchClick: '&'
},
link: function (scope, element, attrs) {
$document.on('click', handleOutsideClick);
element.on('$destroy', function() {
$document.off('click', handleOutsideClick);
});
function handleOutsideClick(e) {
if((element !== e.target || element[0] !== e.target) && !element[0].contains(e.target)) {
scope.$apply(function () {
scope.$eval(scope.outsideSearchClick);
});
}
}
}
};
}
And my element looks like this alongside with the necessary functions.我的元素与必要的功能一起看起来像这样。
vm.search = {
opened: false,
text: ''
};
vm.openSearch = function() {
vm.search.opened = true;
};
vm.closeSearch = function(e, clearSearch) {
vm.search.opened = false;
if(e) {
e.stopPropagation();
}
if(clearSearch) {
vm.search.text = '';
vm.searchResults = {};
}
};
<div class="search" ng-class="{'active': vm.search.opened}"
ng-click="vm.openSearch()"
outside-search-click="vm.closeSearch()"
ng-model-options="{debounce: 500}">
<i class="fo odo-icon-search"></i>
<input type="text" ng-model="vm.search.text">
<div class="search-modal" ng-if="vm.search.opened && vm.search.text">
<div class="search-modal-header">
<div class="close-search" ng-click="vm.closeSearch($event, true)">
<i class="fo odo-icon-cross close-icon"></i>
<span class="close-text">CLOSE</span>
</div>
</div>
<div class="search-modal-body">
<!-- BLAH BLAH BLAH -->
</div>
</div>
I recommend simplifing the directive:我建议简化指令:
documentClick.$inject = ['$document'];
function documentClick($document) {
return {
link: function (scope, element, attrs) {
$document.on('click', handleDocumentClick);
element.on('$destroy', function() {
$document.off('click', handleDocumentClick);
});
function handleDocumentClick(e) {
scope.$apply(function () {
scope.$eval(attrs.documentClick, {$event: e});
});
}
}
};
}
Notice that the directive injects the event as a local with the identifier $event
.请注意,该指令将事件作为具有标识符$event
的本地注入。
<div class="search" ng-class="{'active': vm.search.opened}"
ng-click="vm.openSearch($event)"
document-click="vm.closeSearch($event,false)"
ng-model-options="{debounce: 500}">
<i class="fo odo-icon-search"></i>
<input type="text" ng-model="vm.search.text">
<div class="search-modal" ng-if="vm.search.opened && vm.search.text">
<div class="search-modal-header">
<div class="close-search" ng-click="vm.closeSearch($event, true)">
<i class="fo odo-icon-cross close-icon"></i>
<span class="close-text">CLOSE</span>
</div>
</div>
<div class="search-modal-body">
<!-- BLAH BLAH BLAH -->
</div>
</div>
Instead of adding and removing an event handler, have the handler test for the conditions for which the code should not process the event:不要添加和删除事件处理程序,而是让处理程序测试代码不应处理事件的条件:
vm.openSearch = function(ev) {
ev.stopPropagation();
vm.search.opened = true;
};
vm.closeSearch = function(e, clearSearch) {
if (e.currentTarget == document && !vm.search.opened) {
//ignore event
return;
}
vm.search.opened = false;
if(e) {
e.stopPropagation();
}
if(clearSearch) {
vm.search.text = '';
vm.searchResults = {};
}
};
The avoid the techique of conditionally adding and removing event handlers.避免有条件地添加和删除事件处理程序的技术。 It creates a de facto state which is difficult to understand, debug, test, and maintain.它创建了一个难以理解、调试、测试和维护的事实上的状态。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.