it-roy-ru.com

Хранить селектор jquery в переменной

В следующем примере stored jQuery selector возвращает неправильное значение . Есть возможность сохранить селекторы, а не результат?

Код JS:

// storing the jQuery selectors
var
  $container = $( '.container' ),
  $element1  = $container.find( '.element' ),
  $element2  = $( '.element', $container ),
  $element3  = $( '.element' );

// append elements to the container
for( i=0; i<10; ++i ){
  $container.append( $(element_html) );  
}

// try the stored selectors -> returns 0
console.log( "1: " + $element1.length );
console.log( "2: " + $element2.length );
console.log( "3: " + $element3.length );

Почему, если я использую селекторы контейнера, чтобы найти элементы, это работает? Это потому, что селектор возвращает pointer сопоставленным элементам, а не элементам?

// this works
console.log( "1: " + $container.find( '.element' ).length );
console.log( "2: " + $( '.element', $container )  .length );
console.log( "3: " + $( '.element' )              .length );

jsFiddle демонстрация

30
TheGr8_Nik

У вас есть фундаментальное недопонимание того, что

variableName = $("selector here");

делает. Он не «хранит селектор». Он запускает селектор, который вы передаете для элементов current в DOM, создает объект jQuery, помещает соответствующие элементы в объект jQuery и дает вам ссылку на этот объект jQuery. Селектор не сохраняется (по модулю JQuery внутренности).

Итак, учитывая:

<body>
<div class="foo">x</div>
</body>

Затем:

var $divs = $("div.foo");
console.log($divs.length);        // 1

Дает нам это:

$divs jQuery object pointing at one div in the DOM

Если затем мы добавим еще одно соответствие div:

$('<div class="foo"></div>').appendTo(document.body);

Наш $divs все еще указывает только на первый; добавление другого соответствующего элемента в DOM не оказало влияния на объект jQuery, указанный в $divs.

$divs jQuery object pointing to one div, but there are two in the DOM

Если мы повторно запустим запрос в этот момент:

$divs = $("div.foo");

... тогда мы имеем:

$divs jQuery object pointing at both divs in the DOM

Если у вас есть объект jQuery, содержащий элемент DOM, и вы добавляете элементы потомок к этому элементу DOM, то использование этого объекта jQuery с (скажем) .find будет видеть потомков. Это потому, что родительский элемент DOM уже есть в объекте jQuery. Например, добавление span к одному из divs, на которые мы уже ссылаемся из нашего объекта jQuery:

$divs jQuery object pointing at both divs in the DOM, one has a span now

Если бы мы использовали .find в $divs в тот момент, когда искали span, мы бы нашли его, потому что он является потомком одного из элементов, на который у нас уже была ссылка.

Если вы хотите снова запустить поиск DOM позже, чтобы найти подходящие элементы, вы просто снова используете $(); это подразумевается выше, но для ясности:

var $divs = $("div.foo");
console.log($divs.length);        // 1
$('<div class="foo"></div>').appendTo(document.body);
console.log($divs.length);        // Still 1
$divs = $("div.foo");
console.log($divs.length);        // Now it's 2

Таким образом, «сохранение селектора», когда это необходимо, заключается в хранении строки селектора где-то, а не в объекте jQuery.

100
T.J. Crowder

Я думаю, что принятый ответ превосходен, но его можно интерпретировать так, чтобы предположить, что назначение объектов JQuery переменным всегда небезопасно. Это нормально - до тех пор, пока объект DOM не ссылается на переменные, прежде чем вы получите к нему доступ таким образом, чтобы это влияло на последующий код.

HTML

<div id="banner-message">
    <p>Hello World</p>
    <button>Change view</button>
</div>

JavaScript

// find elements
var banner = $("#banner-message")
var button = $("button")

// handle click and add class
button.on("click", function(){
  banner.addClass("alt");
  banner.hide().html("New HTML").fadeIn(2000);
})

JsFiddle

1
Bob Ray