2015-04-21 29 views
2

我有一個呈現按鈕的簡單指令。如果立即反彈,事件處理程序不會解除綁定

該指令的鏈接功能執行以下操作:

  1. 綁定「的mouseenter」和「鼠標離開」事件。
  2. 取消綁定'mouseenter'和'mouseleave'事件。
  3. 再次綁定'mouseenter'和'mouseleave'事件。

事件處理程序將簡單消息記錄到控制檯。我希望處理程序在mouseenter或mouseleave上被調用一次。然而,它們被執行兩次,就好像第二步從未發生過一樣。

的指令代碼:

function ButtonDirective() { 
    return { 
    restrict: 'E', 
    template: '<button><span ng-transclude></span></button>', 
    transclude: true, 
    replace: true, 
    link: function (scope, element, attrs) {   
     function mouseEnterHandler() { 
     console.log('mouse enter'); 
     } 

     function mouseLeaveHandler() { 
     console.log('mouse leave'); 
     } 

     element.bind('mouseenter', mouseEnterHandler); 
     element.bind('mouseleave', mouseLeaveHandler); 

     element.unbind('mouseenter'); 
     element.unbind('mouseleave'); 

     element.bind('mouseenter', mouseEnterHandler); 
     element.bind('mouseleave', mouseLeaveHandler); 
    } 
    } 
} 

以下plunker說明了問題:

http://plnkr.co/ocXYYZ2jv09Ch7GDRaat

沒有任何人有一個想法,爲什麼它的行爲這樣?

更新:如果您包含jQuery而不是在JQLite上回落,它將起作用。唉,它不適合我。

回答

1

嗯,這個問題似乎是位於JQLite。如果你包含jQuery,它按預期工作。在JQLite中,bind()和unbind()函數只是JQLite.off()和on()的別名。

讓我們考慮一下on()函數的代碼。

on: function jqLiteOn(element, type, fn, unsupported) { 
    // ... 
} 

此函數註冊處理程序的各種類型的事件。顯然,他們爲'mouseenter'和'mouseleave'事件做了一個例外。

if (type === 'mouseenter' || type === 'mouseleave') { 
    // Refer to jQuery's implementation of mouseenter & mouseleave 
    // Read about mouseenter and mouseleave: 
    // http://www.quirksmode.org/js/events_mouse.html#link8 

    jqLiteOn(element, MOUSE_EVENT_MAP[type], function(event) { 
     var target = this, related = event.relatedTarget; 
     // For mousenter/leave call the handler if related is outside the target. 
     // NB: No relatedTarget if the mouse left/entered the browser window 
     if (!related || (related !== target && !target.contains(related))) { 
      handle(event, type); 
     } 
    }); 
} 

這些事件分別映射到('MOUSE_EVENT_MAP [type])到'mouseover'和'mouseout'。

var MOUSE_EVENT_MAP= { mouseleave: "mouseout", mouseenter: "mouseover"}; 

然後是jqLit​​eOn(...)函數調用遞歸本身並註冊爲這些事件映射到一個匿名函數處理。之後它會註冊您的'mouseenter'和'mouseleave'事件。

所以基本上這就是爲什麼事件處理程序被調用多次。

一種解決方法是取消綁定也鼠標懸停及移出事件。

element.unbind('mouseover mouseenter'); 
element.unbind('mouseout mouseleave'); 
0

當解除綁定,您必須指定要解除綁定功能:

element.bind('mouseenter', mouseEnterHandler); 
    element.bind('mouseleave', mouseLeaveHandler); 

    element.unbind('mouseenter', mouseEnterHandler); 
    element.unbind('mouseleave', mouseLeaveHandler); 

    element.bind('mouseenter', mouseEnterHandler); 
    element.bind('mouseleave', mouseLeaveHandler); 
+0

是的,真實的,但這是可選的。也嘗試過使用該功能。同樣的結果。 –

+0

是的你是對的,有趣的是你可以繼續複製解除綁定和數量也會增加。 –

0

行爲是因爲,每mouse enter每次鼠標進入目標元素或它的mouseenter活動將子元素被解僱。

應該mouseovermouseout事件,而不是mouseleavemouse enter

element.bind('mouseover', mouseEnterHandler); 
    element.bind('mouseout', mouseLeaveHandler); 

    element.unbind('mouseover'); 
    element.unbind('mouseout'); 

    element.bind('mouseover', mouseEnterHandler); 
    element.bind('mouseout', mouseLeaveHandler); 
+0

不幸的是,這不是問題。我更新了運動員並從指令中刪除了包含的內容。現在只有按鈕,刪除了跨度。同樣的結果。 –

+0

您是否嘗試使用鼠標懸停和鼠標事件? – mohamedrias

+0

這不是問題。它應該解除事件。我知道這會給任何孩子冒出來,但在這種情況下是沒有的。正如Mathew Berg在他的評論中提到的,你可以根據需要複製綁定/解除綁定序列,並且數量會增加。只是奇怪。 –

相關問題