我正在尝试实现一个文档导航,类似于 Bootstrap 网站上的文档导航。总体来说我已经可以正常工作了,但有一个小方面让我很困扰。
就像在 Bootstrap 上一样,我使用了 affix.js 和 scrollSpy.js 的组合,这很有效。见下文 JSFiddle .
$('#doc_nav').on( "click", "a", function( e ){
// e.preventDefault();
var target = this.hash;
var $target = $(target);
var offset = $target.offset().top;
console.log(offset);
offset = offset - 100;
console.log(offset);
$('html, body').scrollTop( offset );
});
注释掉 e.preventDefault() 后,导航菜单的行为符合预期。向下滚动窗口会导致显示的 div 在菜单上突出显示。单击菜单列表中的一个元素,您将直接转到页面上相应的 div,然后当您滚动离开页面上的该部分时,菜单会相应更新。
在我的“真实”页面上,我有一个高度为 100 像素的固定标题。所以目前,当我点击一个菜单链接时,页面会跳转到所需的部分并将其放置在页面顶部,标题会稍微遮住它。除非我使用 e.preventDefault(),否则上面代码的 scrollTop 部分似乎不起作用。如果您取消注释 fiddle 中的这一行并再次运行它,单击菜单上的“标题 3”链接,您将看到它现在将标题 3 内容放在页面中,从顶部偏移 100 像素。完美。
但是,现在将页面向上滚动到顶部。您会看到“标题 3”列表项保持其 :hover 状态,即使鼠标不在它附近也是如此。就好像 e.preventDefault() 阻止了浏览器检测到鼠标不再悬停在元素上。
在浏览器窗口外的任何地方点击鼠标,问题就解决了。
任何人都可以阐明我在这里做错了什么吗?如何防止 anchor 点击的默认行为,以便我可以控制页面滚动位置,而无需在此过程中停止正确的 CSS 绘制?
出现问题是因为我使用 e.preventDefault() 阻止了浏览器的默认行为,因为我想控制滚动到锚定元素。
我已经在 Firefox 和 IE10 中测试过了。
最佳答案
问题不是 :hover
状态,而是 :focus
状态。
当您单击一个链接时,该链接会获得焦点,因此您可以应用 :focus
样式(与代码中的 :hover
样式相同)。通过阻止默认行为,该链接保持事件状态并且不会失去焦点。
一个快速的解决方案是使用以下方法取消焦点/模糊元素:$(this).blur()
。
在你的代码中它看起来像这样:
$('#doc_nav').on( "click", "a", function( e ){
e.preventDefault();
var target = this.hash;
var $target = $(target);
var offset = $target.offset().top;
console.log(offset);
offset = offset - 100;
console.log(offset);
$(this).blur();
$('html, body').scrollTop( offset );
});
您可以在此处查看演示:https://jsfiddle.net/z32rpe3b/30/
为什么它在使用 e.preventDefault()
时工作正常,但在没有它的情况下却不正确?
这个问题的答案与执行顺序有关。 onclick
事件发生在浏览器中 href
重定向发生之前:
- 没有
e.preventDefault()
,代码被执行,浏览器正确滚动到目标offset - 100
位置(在onclick
),但随后它执行链接href
并滚动到目标offset
。它发生得如此之快,以至于它似乎直接到达了目标位置。 - 使用
e.preventDefault()
,执行代码(滚动到offset - 100
),浏览器不执行href
操作(因此它保持在offset - 100
)。
关于javascript - event.preventDefault() 导致 :hover pseudo class to stick,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29942769/