jQuery: тонкая разница между .has () и: has () - PullRequest
10 голосов
/ 15 октября 2010

При использовании с дочерним селектором >, два варианта jQuery's имеют различное поведение.

Возьми этот HTML:

<div>
  <span>Text</span>
</div>

Сейчас:

$("div:has(>span)");

вернет его, а:

$("div").has(">span");

не будет. Это ошибка или особенность? Сравните здесь: http://jsfiddle.net/aC9dP/


РЕДАКТИРОВАТЬ: Это может быть ошибка или, по крайней мере, недокументированное противоречивое поведение.

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

$("ul:has(>li.active)").show();     // works
$("ul").has(">li.active)").show();  // doesn't work, but IMHO it should

вместо:

$("ul").filter(function () {
  return $(this).children("li.active").length > 0;
}).show();

Я открыл для этого тикет jQuery (7205) .

Ответы [ 2 ]

7 голосов
/ 15 октября 2010

Это происходит потому, что селектор шипения просматривает все элементы Div, у которых есть дочерние объекты span в примере: has. Но в примере .has он передает все DIV в .has (), который затем ищет что-то, что не должно быть изолированным выбором. («Ничего не имеет детей»).

По сути,: has () является частью выбора, но .has () проходит эти div и затем повторно выбирает из них.

В идеале, вы не используете селекторы, подобные этому. Нахождение> в селекторе, вероятно, является ошибкой, так как семантически неудобно. Примечание: дочерний оператор не должен быть автономным.

Sizzle против target.sizzle:

Я всегда говорю о v1.4.2 выпуска jquery для разработки .

.has (строка 3748 jQuery)

Описание: Сократить набор соответствующих элементов до тех, у которых есть потомок , который соответствует селектору или элементу DOM.

Код:

    var targets = jQuery( target );
    return this.filter(function() {
        for ( var i = 0, l = targets.length; i < l; i++ ) {
            if ( jQuery.contains( this, targets[i] ) ) { //Calls line 3642
                return true;
            }
        }
    });

Строка 3642 относится к плагину 2008 года compareDocumentPosition , но важным моментом здесь является то, что мы сейчас просто выполняем два jquery-запроса, где первый выбирает $("DIV"), а следующий - $(">span") (который возвращает ноль), затем мы проверяем детей.

: имеет (строка 3129 jQuery)

Описание: выбирает элементы , которые содержат хотя бы один элемент , соответствующий указанному селектору.

код:

return !!Sizzle( match[3], elem ).length;

Это два разных инструмента: использует 100% и использует цели, переданные ему.

Примечание: если вы считаете, что это ошибка, перейдите к заполнению заявки на ошибку.

1 голос
/ 15 октября 2010

Я думаю, вы могли наткнуться на настоящую ошибку.Проблема может заключаться в том, как вы используете дочерний селектор.Как указал user257493, он не предназначен для использования сам по себе (или, по крайней мере, я не вижу примеров этого в документации.

Проверьте это, хотя. Если вы добавите * переддочерний селектор в .has(), вдруг он работает: http://jsfiddle.net/Ender/FjgZn/

Но если вы сделаете то же самое в селекторе :has(), он перестанет работать! Смотрите здесь: http://jsfiddle.net/Ender/FjgZn/

Определенно, кажется, есть разница в способе реализации этих двух.

...