没有JQuery的mouseenter

Man*_*ans 13 javascript javascript-events

在没有jQuery的情况下,在Javascript中实现mouseenter/mouseleave类似事件的最佳方法是什么?跨浏览器使用的最佳策略是什么?我正在考虑对mouseover/mouseout事件处理程序中的event.relatedTarget/event.toElement属性进行某种检查?

喜欢听你的想法.

sdl*_*rhc 14

(完全改变了我的可怕答案.让我们再试一次.)

假设您有以下基础跨浏览器事件方法:

var addEvent = window.addEventListener ? function (elem, type, method) {
        elem.addEventListener(type, method, false);
    } : function (elem, type, method) {
        elem.attachEvent('on' + type, method);
    };

var removeEvent = window.removeEventListener ? function (elem, type, method) {
        elem.removeEventListener(type, method, false);
    } : function (elem, type, method) {
        elem.detachEvent('on' + type, method);
    };
Run Code Online (Sandbox Code Playgroud)

(很简单,我知道.)

无论何时实施mouseenter/mouseleave,只需将事件附加到正常的mouseover/mouseout事件,然后检查两个重要的细节:

  1. 事件的目标是正确的元素(或正确元素的子元素)
  2. 事件的relatedTarget不是目标的子项

所以我们还需要一个函数来检查一个元素是否是另一个元素的子元素:

function contains(container, maybe) {
    return container.contains ? container.contains(maybe) :
        !!(container.compareDocumentPosition(maybe) & 16);
}
Run Code Online (Sandbox Code Playgroud)

最后一个"问题"是我们如何删除事件监听器.实现它的最快方法是返回我们正在添加的新函数.

所以我们最终得到这样的东西:

function mouseEnterLeave(elem, type, method) {
    var mouseEnter = type === 'mouseenter',
        ie = mouseEnter ? 'fromElement' : 'toElement',
        method2 = function (e) {
            e = e || window.event;
            var target = e.target || e.srcElement,
                related = e.relatedTarget || e[ie];
            if ((elem === target || contains(elem, target)) &&
                !contains(elem, related)) {
                    method();
            }
        };
    type = mouseEnter ? 'mouseover' : 'mouseout';
    addEvent(elem, type, method2);
    return method2;
}
Run Code Online (Sandbox Code Playgroud)

添加mouseenter事件将如下所示:

var div = document.getElementById('someID'),
    listener = function () {
        alert('do whatever');
    };

mouseEnterLeave(div, 'mouseenter', listener);
Run Code Online (Sandbox Code Playgroud)

要删除该事件,您必须执行以下操作:

var newListener = mouseEnterLeave(div, 'mouseenter', listener);

// removing...
removeEvent(div, 'mouseover', newListener);
Run Code Online (Sandbox Code Playgroud)

这并不理想,但剩下的就是实施细节.重要的部分是if子句:mouseenter/mouseleave只是mouseover/mouseout,但是检查你是否针对正确的元素,以及相关的目标是否是目标的子节点.