Разница между: hidden и: not (: visible) в jQuery

Я знаю, что оба селектора jQuery соответствуют элементам, которые не видны (width или height, равным 0, display: none, parent с display: none), и я считаю, что подразумевается, что они должны давать тот же результат в docs.

По соображениям удобочитаемости я предпочел бы использовать :hidden, но я хочу знать:

  • Есть ли какие-либо потенциальные проблемы, которые я должен рассмотреть?
  • Всегда ли получаю тот же результат?
  • Какой вариант имеет лучшую производительность?

Ответы

Ответ 1

  • РЕДАКТИРОВАТЬ 3/22/2016: добавить ответ re: jQuery 1.12/2.2 и 3.0 (* см. конец ответа)
  • РЕДАКТИРОВАТЬ 3/8/2016: улучшите ответ

Элементы можно считать скрытыми по нескольким причинам:

  • У них есть значение CSS display none.
  • Это элементы формы с type="hidden".
  • Их ширина и высота явно установлены на 0.
  • Элемент предка скрыт, поэтому элемент не отображается на странице.

Элементы с visibility: hidden или opacity: 0 считаются видимыми, поскольку они все еще потребляют пространство в макете. Во время анимаций, которые скрывают элемент, элемент считается видимым до конца анимации.

Элементы, которые не находятся в документе, не считаются видимыми; В jQuery нет способа узнать, будут ли они видны при добавлении к документу, поскольку это зависит от применимых стилей.

Селектор :hidden является противоположным селектору :visible. Таким образом, каждый элемент, выбранный :hidden, не выбирается :visible и наоборот.

Во время анимации, чтобы показать элемент, этот элемент считается видимым в начале анимации.

Как определяется :hidden, было изменено в jQuery 1.3.2. Предполагается, что элемент скрыт , если он или любой из его родителей не занимает места в документе. Видимость CSS не учитывается


Разъяснение "ширина или высота, равная 0," - не строго верно, поскольку некоторые браузеры (опера) сообщают меньше 0 в некоторых случаях, поэтому jQuery использует <=0 внутренне.

  • Есть ли какие-либо потенциальные проблемы, которые я должен рассмотреть?
  • Всегда ли получаю тот же результат?
  • Какой вариант имеет лучшую производительность?

1: "Ловушки", кроме очевидных, о которых я не знаю ни одного, несколько субъективны. Я говорю об этом, пытаясь избежать "отрицательных" тестов в коде (не проверять x или! X), поскольку проверки на равенство более понятны для понимания моим мозгом.

2: Да, результат должен быть таким же

3: Re: Производительность Разница между: 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/

Дополнительная информация re: jQuery 1.12/2.2 и 3.0 3/22/2016 edit

В этих версиях произошли значительные улучшения скорости.

Это изменение может дать до 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 возвращаемое значение 2 для visibleElementCount
  • В jQuery 1.12+ и 2.2.0+ и 3.0 вы получите 4 для visibleElementCount. Проверьте, когда вы полагаетесь на этот факт, так как это может быть изменением для ваших страниц.

Ответ 2

Хм.. интересно:)

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

Теперь некоторые другие факты:

css selector 'visibility: hidden;' = 'opacity: 0;' = not display на странице, но occupy space.

css селектор 'display: none;' = not showing in page, а также not occupying space.

jQuery вы можете играть с элементом, у которого 'display: none' style

Пример HTML:

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

Пример CSS:

.display{
  display: none;
}

Check:

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

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

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

Ответ 3

Оба они будут действовать одинаково без каких-либо мыслимых различий.

Оба получат элементы, занимающие место на странице. Это включает элементы с свойством visibility: hidden.

jsfiddle, показывающий это в действии.