jQuery中 :hidden 和 :not(:visible) 的区别

Posted

技术标签:

【中文标题】jQuery中 :hidden 和 :not(:visible) 的区别【英文标题】:Difference between :hidden and :not(:visible) in jQuery 【发布时间】:2013-06-29 19:37:57 【问题描述】:

我知道两个 jQuery 选择器都匹配不可见的元素(widthheight 等于 0,display: none,父级为 display: none),我相信这暗示它们应该产生相同的结果在thedocs.

出于可读性原因,我宁愿使用:hidden,但我想知道:

我是否应该考虑任何潜在的陷阱? 我总是会得到完全相同的结果吗? 哪个选项的性能更好?

【问题讨论】:

它们是同一个东西,:not 可以用于其他东西比如:checked 我同意你关于“可读性”的观点,:hidden:not(:visible) 的否定选择器更好/更容易理解 - 并且实际上应该不知不觉但稍微快一些。 【参考方案1】: 编辑 3/22/2016:添加到答案:jQuery 1.12/2.2 和 3.0(*见答案结尾) 2016 年 3 月 8 日编辑:增强答案

元素被认为是隐藏的有几个原因:

它们的 CSS display 值为 none。 它们是带有type="hidden" 的表单元素。 它们的宽度和高度明确设置为 0。 祖先元素被隐藏,因此该元素不会显示在页面上。

带有visibility: hiddenopacity: 0 的元素被认为是可见的,因为它们仍然会占用布局中的空间。在隐藏元素的动画期间,该元素被视为在动画结束之前可见

不在文档中的元素被认为是不可见的; jQuery 无法知道它们在附加到文档时是否可见,因为它取决于适用的样式。

:hidden 选择器与 :visible 选择器相反。因此,:hidden 选择的每个元素都不会被:visible 选择,反之亦然。

在显示元素的动画期间,该元素被认为是在动画开始时可见

如何确定:hidden 在 jQuery 1.3.2 中发生了变化。 如果元素或其任何父元素不占用文档中的空间,则假定元素被隐藏。 不考虑 CSS 可见性


澄清“宽度或高度等于 0” - 并非严格正确,因为某些浏览器(歌剧)在某些情况下报告小于 0,因此 jQuery 内部使用 <=0

    我是否应该考虑任何潜在的陷阱? 我总是会得到完全相同的结果吗? 哪个选项的性能更好?

1:“陷阱”除了我不知道的明显之外,有些主观。我这样说是因为我试图避免代码中的“负面”测试(不是 x 或 !x 类型检查),因为相等性检查更直观地让我的大脑理解。

2:是的,结果应该是一样的

3:回复:性能 区别:RE:1.10.1 版本

可见条件检查使用内部不隐藏:

jQuery.expr.filters.visible = function( elem ) 
    return !jQuery.expr.filters.hidden( elem );
;

因此可以说严格来说“隐藏”应该更有效地避免“非”条件。

在内部,jQuery 使用“从右到左”选择器,因此选择器在某些情况下会产生更大的差异。

为了性能,使用

$(selector).filter(':hidden')

$(selector).not(':visible') 

而不是任何一个

$('selector:not(:visible)') 

$('selector:hidden')

这是为什么? :hidden 是一个 jQuery 扩展,因此无法利用原生 DOM querySelectorAll() 方法提供的性能提升。 (请参阅 Sizzle 引擎的从右到左解析,了解它是如何发生的)

选择器的形式/格式

这是因为对于$('selector:hidden') 表单,它会选择(遍历 DOM)

    所有隐藏元素优先, 然后从该集合中选择与选择器匹配的那些。最好首先匹配选择器,然后过滤该集中隐藏的选择器。

内部“isHidden”函数:(jQuery 1.10.1)

function isHidden( elem, el ) 
    // isHidden might be called from jQuery#filter function;
    // in that case, element will be second argument
    elem = el || elem;
    return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem );

例如用在.showHide内部如:

if ( elem.style.display === "" && isHidden( elem ) ) 

值得注意的是defaultPrefilter中的“隐藏”属性是:

hidden = elem.nodeType && isHidden( elem ),

关于风格的特别说明:

将元素 CSS 设置为:

document.getElementById("hide-me").style.visibility = "hidden";

非常快。

您也可以非常快速地检测到这一点:

document.getElementById("hide-me").style.visibility  === "hidden";

请记住,尽管该元素仍会占用空间,而 document.getElementById("hide-me").style.display = "block"; 似乎确实使它可见,但请记住,某些 PARENT 可能不可见,因此该元素可能仍被视为“隐藏” - 并且 jQuery 确实检测到了这一点(见上文)

其他参考:https://api.jquery.com/hidden-selector/

关于 jQuery 1.12/2.2 和 3.0 3/22/2016 编辑的附加信息

这些版本的速度有了一些显着提升。

参考这篇文章:https://github.com/jquery/jquery/issues/2042 相关参考:https://github.com/jquery/sizzle/issues/315#issuecomment-74336936

此更改可带来高达 1600% 的速度提升哇!尽可能利用缓存——据我观察,这些选择器经常发生这种情况。如果您在这方面需要改进或存在顾虑,请同时测试您的页面,如果您的页面中大量使用,则使用用例进行测试。

您应该会看到 .show().hide() 带来的性能提升。

jQuery 1.12+ 和 2.2.0+ 和 3.0 修改了 :visible:hidden 过滤器的含义。如果元素有布局框,它们将被视为:visible。这包括宽度和/或高度为零的那些。对于您的选择器,请注意计数。示例:没有内容的内联元素和 br 元素现在将由 :visible 过滤器选择。

页面标记示例:

<div>
</div>
<span></span>
<br />
<p>
</p>

具有以下部门:

var visibleElementCount = $('body').find(':visible').length;
在 jQuery 1.11.1 和 2.1.4 中,visibleElementCount 返回值 2 在 jQuery 1.12+ 和 2.2.0+ 和 3.0 中,visibleElementCount 将获得 4。测试您何时依赖此事实,因为这可能会对您的网页造成重大变化。

【讨论】:

在走 RTL 时,Sizzle 是否真的枚举了简单的选择器?只是好奇——我只知道原生 CSS 选择器引擎会枚举复合选择器 RTL 并自动解析每个选择器,因为它没有理由总是从最右边的简单选择器开始。 哦,我看错了。我猜selector 代表整个复合 CSS 选择器,:not()/:visible/:hidden 分别对匹配该集合的元素进行操作。无论哪种方式,它可能都不是很重要。实施细节等等。 差异通常并不显着,但是如果您遇到性能问题,具有多个类、子级等的复杂选择器可能会产生负面影响。更短的可能更好,但更短(复杂)的选择器不会更快:示例 $('#myid&gt;.child1&gt;.gchild&gt;.ggchild:not(".fred"):not(:hidden)') - 特别是 .child1etc 在大型 DOM 中有许多对等点。【参考方案2】:

嗯..有趣:)

:hidden = :not(:visible) = css selector 'display: none;'

现在还有一些其他事实:

css 选择器 'visibility: hidden;' = 'opacity: 0;' = not display 在页面中但 occupy space.

css 选择器'display: none;' = not showing in pagenot occupying space

通过 jQuery,您可以使用具有 'display: none' 样式的元素

HTML 示例:

<input type='text' class='display' value='Display' />

CSS 示例:

.display
  display: none;

检查:

alert($('.display').val());// Display

$('.display').val('Hello');

alert($('.display').val());// Hello

【讨论】:

【参考方案3】:

他们都会以相同的方式行事,没有想象中的区别。

两者都会为您提供占用页面空间的元素。这包括具有visibility: hidden 属性的元素。

jsfiddle showing this in action.

【讨论】:

以上是关于jQuery中 :hidden 和 :not(:visible) 的区别的主要内容,如果未能解决你的问题,请参考以下文章

jQuery中 :hidden 和 :not(:visible) 的区别

jQuery中 :hidden 和 :not(:visible) 的区别

jQuery中 :hidden 和 :not(:visible) 的区别

jQuery中 :hidden 和 :not(:visible) 的区别

validate验证jquery chosen相关问题

使用 jQuery 选择样式为“visibility:visible”或“visibility:hidden”而不是“display:none”的项目