如何取消绑定().hover()而不是.click()?
Posted
技术标签:
【中文标题】如何取消绑定().hover()而不是.click()?【英文标题】:How to unbind() .hover() but not .click()? 【发布时间】:2014-08-05 16:22:48 【问题描述】:我正在使用 Bootstrap 3 创建一个站点,并且还使用了一个脚本,该脚本使用 .hover() 函数使下拉菜单出现在悬停时。我试图通过使用 enquire.js 在小型设备上防止这种情况。我正在尝试使用以下代码取消绑定元素上的 .hover() 事件:
$('.dropdown').unbind('mouseenter mouseleave');
这解除了该脚本的 .hover 绑定,但显然它也删除了 .click() 事件(或任何引导程序使用的),现在当我悬停或单击元素时,什么也没有发生。
所以我只想知道如何删除该元素上的 .hover(),它源自该脚本,但不更改任何其他内容。
非常感谢任何帮助。
谢谢!
编辑:以下是我为悬停函数调用处理程序的方式:
$('.dropdown').hover(handlerIn, handlerOut);
function handlerIn()
// mouseenter code
function hideMenu()
// mouseleave code
我正在尝试用这段代码解除它们的绑定。
$('.dropdown').unbind('mouseenter', showMenu);
$('.dropdown').unbind('mouseleave', hideMenu);
但它不起作用。
请帮忙!
**Edit2:**基于 Tieson T.的回答:
function dropdownOnHover()
if (window.matchMedia("(min-width: 800px)").matches)
/* the view port is at least 800 pixels wide */
$('.dropdown').hover(handlerIn, handlerOut);
function handlerIn()
// mouseenter code
function hideMenu()
// mouseleave code
$(window).load(function()
dropdownOnHover();
);
$(window).resize(function()
dropdownOnHover();
);
Tieson T. 提供的代码效果最好;但是,当我调整窗口大小时,直到从任何方向到达断点,效果都不会改变。也就是说,如果窗口加载到 800px 以上,悬停效果就会出现,但如果我把窗口变小,它仍然存在。我尝试用 window.load 和 window.resize 调用函数,但还是一样。
编辑 3: 我实际上是在尝试在悬停而不是单击时创建 Bootstrap 下拉菜单。这是更新的 jsFiddle:http://jsfiddle.net/CR2Lw/2/
请注意: 在 jsFiddle 示例中,我可以使用 css :hover 属性并将 dropdow-menu 设置为 display:block。但是因为我需要设置下拉列表样式的方式,链接和下拉列表之间需要有一些空间(这是必须的),所以我必须找到一个 javascript 解决方案。或一个非常棘手的css解决方案,其中链接和下拉菜单之间有abot 50px的空间,当用户将鼠标悬停在链接上并且出现下拉菜单时,当用户尝试访问它时下拉菜单不应该消失.希望这是有道理的,谢谢。
编辑 4 - 第一个可能的解决方案: http://jsfiddle.net/g9JJk/6/
【问题讨论】:
我不明白为什么 JS 会工作,如果 CSS 不行。你能帮我理解你在 .dropdown 类上的 mouseenter / mouseleave 与 .dropdown:hover 的行为有何不同吗?我在这里错过了什么? 实际上,css 确实有效。只是由于我的设计限制,我无法使用它。基本上,链接和下拉菜单出现的位置之间存在“间隙”,因此当用户尝试转到下拉菜单时(当用户将鼠标悬停在链接上时它出现后),下拉菜单就会消失,因为自然链接不会保持悬停状态,因为用户会越过该间隙到达下拉菜单。 我明白这一点。因此,如果您在 mouseleave 上隐藏菜单,也会发生同样的情况……这是我没有得到的部分。我的意思是你实际上并没有展示你在处理程序中所做的事情,但你所拥有的似乎会产生完全相同的行为,不是吗?是否缺少功能?也许 handlerOut 是我所缺少的以及 hideMenu 的实际工作方式。 最后一个 jsFiddle 似乎可以完成这项工作。这是一个值得尝试和解决的有趣问题……很高兴你想通了。 是的,很高兴它成功了。感谢所有的帮助。 【参考方案1】:有选择地应用悬停可能更容易,而不是稍后尝试将其删除。您可以使用window.matchMedia,并且仅当浏览器的屏幕尺寸暗示桌面浏览器(或较大的平板电脑)时才应用您的脚本:
if (window.matchMedia("(min-width: 800px)").matches)
/* the view port is at least 800 pixels wide */
$('.dropdown').on(
mouseenter: function ()
//stuff to do on mouse enter
,
mouseleave: function ()
//stuff to do on mouse leave
);
else
$('.dropdown').off('mouseenter, mouseleave');
由于它不是 100% 支持的,您需要为那些没有原生支持的浏览器添加一个 polyfill:https://github.com/paulirish/matchMedia.js/
如果您使用的是 Moderizr,则该 polyfill 已包含在该库中,因此您可以继续使用。
【讨论】:
嗨。谢谢你的回答。我想我已经非常接近解决方案了;但是,请参阅我更新后的问题,了解我在调整窗口大小时遇到的问题。 那是因为绑定已经被应用了;调整视口大小不是页面请求,因此 DOM 不会改变。 那么我该怎么做才能使该元素上的 hover() 函数仅适用于大于 800px 的设备? @user3570481 试试上面的编辑;注意从.hover
到.on
的变化,如果视口不再匹配,我们使用.off
删除这些处理程序。
不,它的行为仍然相同,当窗口调整大小时不会切换到另一个。【参考方案2】:
我仍然不明白您打算如何在将鼠标悬停在下拉元素上时显示下拉菜单,部分原因是您的问题中没有足够的代码,但这与此答案无关。
我认为处理 mouseenter 事件处理部分的一种更简单的方法不是使用 off()/on() 在特定断点处取消绑定/绑定事件,而是在事件发生时做一个简单的检查触发。换句话说,是这样的:
$('.dropdown').on('mouseenter', function()
if($('.navbar-toggle').css('display') == 'none')
$(this).children('.dropdown-menu').show();
;
);
$('.dropdown-menu').on('click', function()
$(this).hide();
);
这是一个有效的小提琴:http://jsfiddle.net/jme11/g9JJk/
基本上,在 mouseenter 事件中,我正在检查是否显示菜单切换,但如果您愿意,您可以在此时检查 window.width()。在我看来,切换元素的显示值更容易遵循,它还确保如果您更改“折叠”菜单的媒体查询断点,代码将保持同步,而无需更新硬编码值(例如 768px)。
点击关闭菜单不需要检查,因为它没有在“折叠”菜单下拉菜单上触发时看到的有害影响。
从用户体验的角度来看,我仍然不喜欢这个。我宁愿点击打开菜单也不愿点击关闭在悬停事件中打开的菜单,但也许你有一些神奇的计划来触发隐藏方法的其他方式。也许您打算注册一个 mousemove 事件,以检查鼠标是否在 .dropdown + 50px + .dropdown-menu 或类似的范围内的任何位置...我真的很想知道您打算如何执行此操作(好奇心有点害死我)。也许您可以更新您的代码以显示最终结果。
编辑:感谢您发布您的解决方案!
【讨论】:
嗨!非常感谢您的回答。您检查 .toggle 显示的第一个答案帮助我找到了解决方案。请检查我的最后一次更新。除非我遗漏了什么,否则我认为它工作得很好。 哦,谢天谢地,您发布了您的解决方案……这让我发疯了!聪明,顺便说一句,我没想过在上面放一个计时器。我非常喜欢它。我想我将删除答案中的 css 选项以保持简洁。 嘿,你为什么不把你的答案的链接添加到最后的小提琴,这样我就可以把它标记为正确的答案。以上是关于如何取消绑定().hover()而不是.click()?的主要内容,如果未能解决你的问题,请参考以下文章
jQuery click fallback sans hover ipad
js/jquery 如何判断当前是不是具有某个事件 比如说是不是具有hover事件
如何使 CSS3 悬停过渡只运行一次,而不是在用户“取消悬停”后“倒带”?