[英]Add and remove event listener when element receives and loses a class
我有一個小的搜索按鈕,一旦用戶點擊放大鏡圖標,它就會展開並顯示輸入。 在這一點上,我給我的搜索元素.active
類。 一旦用戶開始輸入,就會顯示一個帶有搜索結果的“模態”窗口。 我想要做的是在外部單擊時添加和刪除我的事件偵聽器(除了模態窗口、搜索按鈕和輸入之外的任何其他地方)。
只是為了澄清以上所有內容都在搜索元素中,因此它們都是搜索的子元素。
當元素從 DOM 中刪除時,我設法刪除了事件偵聽器,但我無法這樣做,以便在元素接收和丟失.active
類時添加和刪除它。 我怎么可能這樣做?
我的指令如下所示。
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);
});
}
}
}
};
}
我的元素與必要的功能一起看起來像這樣。
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>
我建議簡化指令:
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});
});
}
}
};
}
請注意,該指令將事件作為具有標識符$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>
不要添加和刪除事件處理程序,而是讓處理程序測試代碼不應處理事件的條件:
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 = {};
}
};
避免有條件地添加和刪除事件處理程序的技術。 它創建了一個難以理解、調試、測試和維護的事實上的狀態。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.