jQuery: это: $(this).next().next() работает, но $(this).next('.div') не работает

Ладно, я пытаюсь заставить этот набор информации спрятаться по отдельности.

<img class="arrow" src="images/navigation/arrowright.png">
<H2>More Information</H2>
<div class="box">
    <h2>Bibendum Magna Lorem</h2>
    <p>Cras mattis consectetur purus sit amet fermentum.</p>
</div>

<img class="arrow" src="images/navigation/arrowright.png">
<H2>A Second Group of Information</H2>
<div class="box">
    <h2>Bibendum Magna Lorem</h2>
    <p>Cras mattis consectetur purus sit amet fermentum.</p>
</div>

Он работает, когда я набираю это:

$(".arrow").click(function() {
    $(this).next().next().slideToggle();
});

но не тогда, когда я делаю это:

$(".arrow").click(function() {
    $(this).next('.box').slideToggle();
});

Что происходит, что второй вариант не работает? Я был в этом в течение нескольких дней и не могу чертовски понять это! Я ценю ваш вклад!


person fjaxyu    schedule 16.05.2015    source источник
comment
К вашему сведению, отступ вашего HTML выглядит так, как будто у вас есть родительские/дочерние отношения между элементами, которых на самом деле нет (своего рода вводящий в заблуждение способ показать HTML).   -  person jfriend00    schedule 17.05.2015
comment
ах, да, это имеет смысл, совершенно мой плохой! Я довольно новичок в этом, поэтому я все еще привыкаю ко всему. Спасибо, что указали, что вы!   -  person fjaxyu    schedule 17.05.2015


Ответы (1)


Проблема

Если вы посмотрите на документацию для .next(selector), она не "найдет" следующего брата, соответствующего селектору. . Скорее, он смотрит ТОЛЬКО на следующего брата и возвращает этот элемент, ТОЛЬКО если он соответствует селектору, который вам не нужен.

Вот что говорит документ для .next():

Описание: Получите ближайший следующий брат каждого элемента в наборе совпадающих элементов. Если предоставлен селектор, он извлекает следующего брата, только если он соответствует этому селектору.

Итак, вы можете видеть, что .next(".box") будет смотреть на элемент h2, который сразу следует за вашим элементом .arrow (это следующий родственный элемент), а затем сравнивать его с селектором .box, и, поскольку они не совпадают, он вернет пустой объект jQuery.


Решение с использованием .nextAll()

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

$(this).nextAll(".box").eq(0).slideToggle();

Это находит всех потомков, которые соответствуют селектору, а затем извлекает только первый.


Создайте собственный метод .findNext()

Я так часто задавался вопросом, почему в jQuery нет метода для этого, что я сделал его сам:

// get the next sibling that matches the selector
// only processes the first item in the passed in jQuery object
// designed to return a jQuery object containing 0 or 1 DOM elements
jQuery.fn.findNext = function(selector) {
    return this.eq(0).nextAll(selector).eq(0);
}

И тогда вы просто использовали бы:

$(this).findNext(".box").slideToggle();

Вариант: добавьте больше структуры в HTML, чтобы сделать все проще и гибче

К вашему сведению, общий подход к подобным проблемам заключается в том, чтобы поместить содержащий div вокруг каждого набора элементов DOM, например:

<div class="container">
    <img class="arrow" src="images/navigation/arrowright.png">
    <H2>More Information</H2>
    <div class="box">
            <h2>Bibendum Magna Lorem</h2>
            <p>Cras mattis consectetur purus sit amet fermentum.</p>
    </div>
</div>

<div class="container">
     <img class="arrow" src="images/navigation/arrowright.png">
     <H2>A Second Group of Information</H2>
     <div class="box">
            <h2>Bibendum Magna Lorem</h2>
            <p>Cras mattis consectetur purus sit amet fermentum.</p>
     </div>    
</div>

Затем вы можете использовать код, который немного менее чувствителен к точному расположению элементов:

$(".arrow").click(function() {
    $(this).closest(".container").find(".box").slideToggle();
});

Это идет к содержащему и общему родителю, используя .closest(), а затем использует .find(), чтобы найти элемент .box в этой группе.

person jfriend00    schedule 16.05.2015
comment
более выразительно: $(this).nextAll(".box").first().slideToggle(); - person Nick Humphrey; 27.03.2017
comment
Больше структуры в HTML, чтобы сделать вещи проще и гибче - person HPWD; 16.01.2019