Как получить родителя n-го уровня элемента в jQuery?

151

Когда я хочу получить, например, 3-го уровня родителя элемента, я должен написать $('#element').parent().parent().parent()Есть ли более оптимальный метод для этого?

Артур Кейан
источник
2
Я хочу дать только номер (Уровень) и получить элемент, потому что у моего элемента может не быть идентификатора или имени
Calss
1
Если вы планируете использовать эту функциональность повторно, оптимальным решением будет создание плагина jQuery.
zzzzBov
3
См jsperf.com/jquery-get-3rd-level-parent для некоторых сравнений производительности
a'r
1
Еще одним хорошим инструментом является функция ".closest ()". $ ('li.item'). closest ('div') даст вам DIV, который является ближайшим предком li.item. Хорошо, когда вы не знаете, на сколько уровней находится элемент, но вы действительно знаете его тэг / класс / что-то еще.
Грэм

Ответы:

267

Так как parent () возвращает элементы-предки, упорядоченные от ближайших к внешним, вы можете связать их в eq () :

$('#element').parents().eq(0);  // "Father".
$('#element').parents().eq(2);  // "Great-grandfather".
Фредерик Хамиди
источник
могу ли я использовать этот $ ('# element'). parent () [2]? или это должно быть с eq (2)
Артур Кейан
1
это не будет работать для нескольких элементов выбора, более безопасный способ будет:$('.element').first().parents().eq(num);
zzzzBov
6
@Arthur, использование [2]вернет базовый элемент DOM, использование eq(2)вернет объект jQuery.
Фредерик Хамиди
1
@zzzzBov, очень верно, но в случае спрашивающего будет выбран только один элемент (потому что он соответствует идентификатору).
Фредерик Хамиди
Если вы посмотрите на идентификатор "#element", он будет возвращать только один элемент, поскольку именно так работает поиск идентификаторов, они возвращают первый элемент с этим идентификатором в DOM. С другой стороны, если вы сделали «div # element» или селектор класса, вы были бы правы.
Генри
29

Зависит от ваших потребностей, если вы знаете, какого родителя вы ищете, вы можете использовать селектор .parents ().

Например: http://jsfiddle.net/HenryGarle/Kyp5g/2/

<div id="One">
    <div id="Two">
        <div id="Three">
            <div id="Four">

            </div>
        </div>
    </div>
</div>


var top = $("#Four").parents("#One");

alert($(top).html());

Пример использования индекса:

//First parent - 2 levels up from #Four
// I.e Selects div#One
var topTwo = $("#Four").parents().eq(2);

alert($(topTwo ).html());
Генри
источник
Я сейчас таким образом, но хочу дать уровень
Артур Кейан
3
Читайте дальше вниз по ответу, и все будет раскрыто! (Я дал вам примеры уровня)
Генри
Это хорошо работает для всех других видов селекторов. Например, если вы хотите получить список всех родителей и родителей родителей определенного класса, это вернет их.
Даркский
8

Вы можете дать целевому родителю идентификатор или класс (например, myParent), а ссылка на $('#element').parents(".myParent")

Джозеф Марикл
источник
Я хочу дать только номер и получить элемент, потому что у моего элемента может не быть идентификатора или имени
calss
6

Более быстрый способ - использовать javascript напрямую, например.

var parent = $(innerdiv.get(0).parentNode.parentNode.parentNode);

Это работает значительно быстрее в моем браузере, чем цепочка .parent()вызовов jQuery .

Смотрите: http://jsperf.com/jquery-get-3rd-level-parent

a'r
источник
«Значительно быстрее», мы смотрим примерно на порядок с точки зрения разницы в скорости (запуск jQuery 1.10.1 на Chrome 51). Определенно стоит реализовать, если вы настраиваете на скорость.
Иэн Фрейзер
5

Не нашел никакого ответа с помощью, closest() и я думаю, что это самый простой ответ, когда вы не знаете, на сколько уровней требуется требуемый элемент, поэтому отправка ответа:
вы можете использовать closest()функцию в сочетании с селекторами, чтобы получить первый элемент, который соответствует при движении вверх от элемента:

('#element').closest('div')    // returns the innermost 'div' in its parents
('#element').closest('.container')    // returns innermost element with 'container' class among parents
('#element').closest('#foo')    // returns the closest parent with id 'foo'
датчанин
источник
3

Это просто. Просто используйте

$(selector).parents().eq(0); 

где 0 - родительский уровень (0 - родительский, 1 - родительский и т. д.)

zatatatata
источник
3

Просто добавьте :eq()селектор вот так:

$("#element").parents(":eq(2)")

Вы просто указываете, какой родитель: 0 для непосредственного родителя, 1 для деда, ...

MBO
источник
Этот способ - самый быстрый способ получить работу. Вот эталонный тест, чтобы доказать это: jsperf.com/jquery-get-element-s-nth-parent
java-man-script
3

Если вы планируете использовать эту функциональность повторно, оптимальным решением будет создать плагин jQuery:

(function($){
$.fn.nthParent = function(n){
  var $p = $(this);
  while ( n-- >= 0 )
  {
    $p = $p.parent();
  }
  return $p;
};
}(jQuery));

Конечно, вы можете расширить его, чтобы включить дополнительный селектор и другие подобные вещи.

Одно замечание: здесь используется 0основанный индекс для родителей, так nthParent(0)же, как и вызов parent(). Если вы предпочитаете 1индексирование на основе, используйтеn-- > 0

zzzzBov
источник
Я думаю, что вы найдете эту часть быстрее: var p = 1 + n; while (p--) { $p = $p.parent(); }и если вы хотите изменить на 1, Javascript - это «falsey», который вы можете использовать: while (n--) { $p = $p.parent();} сохранение условной проверки
Mark Schultheiss
@ Mark Schultheiss, речь идет не только о скорости, но и о надежности. Что происходит с вашей функцией, если кто-то невежливо звонит nthParent(-2)? Ваш пример сломан.
zzzzBov
ИЛИ просто вернитесь(function($) { $.fn.nthParent = function(n) { return $(this).parents().eq(n); }; }(jQuery));
Марк Шультхайс
@ Марк Шультхайс, опять же, надежность. Моя функция возвращает nthParent для каждого элемента в выборе, ваша функция возвращает n-й элемент в списке, parentsкоторый будет неправильным для выборов с более чем одним элементом.
zzzzBov
Значение true в отношении -2, и, как в вашем примере, использование var p = n >? (1 + n):1; вместо этого вернет первого родителя в этом случае, а не «ничего» - или где это прерывает цикл в моем примере. ТАК, наверное, так и должно быть: (function($) { $.fn.nthParent = function(n) { var $p = $(this); if (!(n > -0)) { return $() }; var p = 1 + n; while (p--) { $p = $p.parent(); } return $p; }; }(jQuery)); если вы не хотите ничего возвращать.
Марк Шультхайс
3

Если у вас есть общий родительский DIV можно использовать parentsUntil () ссылка

например: $('#element').parentsUntil('.commonClass')

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

ashishyadaveee11
источник
1

Вы также можете использовать:

$(this).ancestors().eq(n) 

пример: $(this).ancestors().eq(2)-> родитель родителя this.

Моуна Шейхна
источник
0

Вы можете использовать что-то вроде этого:

(function($) {
    $.fn.parentNth = function(n) {
        var el = $(this);
        for(var i = 0; i < n; i++)
            el = el.parent();

        return el;
    };
})(jQuery);

alert($("#foo").parentNth(2).attr("id"));

http://jsfiddle.net/Xeon06/AsNUu/

Алекс Турпин
источник
1
Не downvoter, но это, вероятно, худшее решение (т.е. неэффективное) здесь.
zatatatata
0

использование eq похоже для захвата динамического DOM, а использование .parent (). parent () - для захвата DOM, который был изначально загружен (если это вообще возможно).

Я использую их оба для элемента, к которому применены классы для onmouseover. eq показывает классы, а .parent (). parent () - нет.


источник