40

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

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

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

3 回答 3

55
  • 编辑 3/22/2016:添加到答案:jQuery 1.12/2.2 和 3.0(*见答案结尾)
  • 编辑 3/8/2016:增强答案

元素可以被认为是隐藏的,原因如下:

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

带有visibility: hidden或的元素opacity: 0被认为是可见的,因为它们仍然占用布局中的空间。在隐藏元素的动画期间,该元素被认为是可见的,直到动画结束

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

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

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

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


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

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

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

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

3:回复:性能差异:回复: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 扩展,因此无法利用原生 DOMquerySelectorAll()方法提供的性能提升。(请参阅 Sizzle 引擎的从右到左的解析,了解它是如何发生的)

选择器的形式/格式

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

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

内部“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 编辑

这些版本有一些显着的速度改进。

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

.show()您应该会因此而看到性能的提高.hide()

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

页面标记示例:

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

与以下部门:

var visibleElementCount = $('body').find(':visible').length;
  • 在 jQuery 1.11.1 和 2.1.4 返回值 2 为visibleElementCount
  • 在 jQuery 1.12+ 和 2.2.0+ 和 3.0 中,您将获得 4 for visibleElementCount. 测试您何时依赖此事实,因为这可能是您页面的重大更改。
于 2013-07-02T13:23:44.090 回答
5

嗯..有趣:)

: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
于 2013-07-02T13:17:34.127 回答
3

他们都将以相同的方式行事,没有可以想象的差异。

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

jsfiddle 展示了这一点。

于 2013-07-02T12:29:42.063 回答