簡體   English   中英

元素接收和丟失類時添加和刪除事件偵聽器

[英]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的本地注入。

HTML:

<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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM