jQuery первый ребенок «этого»

317

Я пытаюсь передать "this" из отрезка, по которому щелкнули, в функцию jQuery, которая затем может выполнить jQuery для первого дочернего элемента этого нажатого элемента. Не могу понять это правильно ...

<p onclick="toggleSection($(this));"><span class="redClass"></span></p>

Javascript:

function toggleSection(element) {
  element.toggleClass("redClass");
}

Как мне сослаться на: first-child элемента?

macca1
источник
4
Если вы используете jQuery, почему бы вам не связать обработчики событий, используя также jQuery?
Вивин Палиат
2
потому что обработчики событий bind должны быть инициализированы в document.ready (), который добавляет снижение производительности (это приложение для IE6). или есть другой способ?
macca1
Хм .. не уверен. Связывание с использованием jQuery является стандартным способом (если вы уже используете jQuery). Какое снижение производительности вы испытываете при использовании jQuery(document).ready(...)?
Вивин Палиат
Это большое приложение с 7+ разработчиками. Первоначально прошло 4 с половиной секунды, прежде чем я попытался немного его почистить. Так что я бы предпочел не добавлять к нему больше, когда мне не нужно :)
macca1

Ответы:

482

Если вы хотите применить селектор к контексту, предоставленному существующим набором jQuery, попробуйте функцию find () :

element.find(">:first-child").toggleClass("redClass");

Йорн Шу-Роде отметил, что вы, вероятно, захотите найти только первого прямого потомка элемента контекста, отсюда и дочерний селектор (>). Он также указывает, что вы также можете использовать функцию children () , которая очень похожа на функцию find (), но ищет только один уровень глубоко в иерархии (это все, что вам нужно ...):

element.children(":first").toggleClass("redClass");
Shog9
источник
1
Спасибо! работает отлично. Я предполагаю, что другие способы, перечисленные ниже, также будут работать.
macca1
6
Я считаю, что find()поиск по всем потомкам, и :first-childможет соответствовать один элемент на родителя. Следовательно, этот запрос может возвращать несколько элементов. Или я ошибаюсь?
Йорн Шоу-Роде
19
Я знаю, что это старый вопрос / ответ, но использование селектора ">" без родителя в этом селекторе не рекомендуется (например, ">: firstchild") с jQuery 1.8. Я предлагаю вместо того, чтобы использовать element.children(":first-child")илиelement.children().first();
Кевин Б.
3
@KevinB, по-видимому, они решили не осудить его в конце концов
Альнитак
1
лучшим подходом было бы НЕ выполнять итерации по всем элементам, а затем выбирать первый, как некоторые предлагали здесь. Это было бы плохо.
vsync
74

Используйте childrenфункцию с :firstселектором, чтобы получить единственный первый потомок element:

element.children(":first").toggleClass("redClass");
Йорн Шоу-Роде
источник
element.children () [0] .toggleClass ( "redClass");
Закос
5
@Zakos:TypeError: Object [object HTMLAnchorElement] has no method 'toggleClass'
Йорн Шоу-Роде
51

Я добавил тест jsperf, чтобы увидеть разницу в скорости для разных подходов, чтобы получить первого ребенка (всего более 1000 детей)

дано, notif = $('#foo')

JQuery способы:

  1. $(":first-child", notif) - 4304 операций в секунду - самый быстрый
  2. notif.children(":first") - 653 операции в секунду - на 85% медленнее
  3. notif.children()[0] - 1416 операций в секунду - на 67% медленнее

Родные способы:

  1. JavaScript native ' ele.firstChild- 4934323 операций в секунду (все вышеперечисленные подходы на 100% медленнее по сравнению с firstChild)
  2. Собственный DOM ele от jQery: notif[0].firstChild- 4,913,658 операций в секунду

Итак, первые 3 подхода jQuery не рекомендуются, по крайней мере, для первого ребенка (я сомневаюсь, что это будет иметь место и со многими другими). Если у вас есть объект jQuery и вам нужно получить first-child, то получите нативный элемент DOM из объекта jQuery, используя ссылку на массив [0] (рекомендуется) или .get(0)и используйте ele.firstChild. Это дает те же результаты, что и при обычном использовании JavaScript.

все тесты выполнены в Chrome Canary build v15.0.854.0

manikanta
источник
20
На самом деле, результаты firstChildне будут такими же, как у jQuery children()или запросов селектора. firstChildбудет включать текстовые узлы, которые редко желательны. contents()Функция jQuery будет включать их, но children()не будет. Более новые браузеры поддерживают firstElementChildпервый дочерний элемент, но IE <9 не поддерживает его. Таким образом, если вы используете, firstChildвы должны вручную найти первый нетекстовый дочерний узел.
Макс
1
$(":first-child", notif)должно быть $(":first", notif)для ожидаемого поведения. Первый вернет всех потомков первого-дочернего элемента.
Дражен Бжеловук
18
element.children().first();

Найти всех детей и получить первый из них.

Бишал Паудель
источник
1
Безусловно самый простой способ и более эффективный, чем .children(':first').
Гра Дабл
3
Как это более эффективно? Кажется, что он получает всех детей, затем берет первого, а не только первого ребенка.
Энтони МакГрат,
9

Ты пробовала

$(":first-child", element).toggleClass("redClass");

Я думаю, что вы хотите установить свой элемент в качестве контекста для вашего поиска. Возможно, есть лучший способ сделать это, и некоторые другие гуру jQuery подскажут вам здесь :)

theIV
источник
3
это потерпит неудачу, если у elementнего есть внуки
Alnitak
4

Я только что написал плагин, который использует, .firstElementChildесли это возможно, и возвращается к итерации по каждому отдельному узлу, если это необходимо:

(function ($) {
    var useElementChild = ('firstElementChild' in document.createElement('div'));

    $.fn.firstChild = function () {
        return this.map(function() {
            if (useElementChild) {
                return this.firstElementChild;
            } else {
                var node = this.firstChild;
                while (node) {
                    if (node.type === 1) {
                        break;
                    }
                    node = node.nextSibling;
                }
                return node;
            }
        });
    };
})(jQuery);

Это не так быстро, как решение для чистого DOM, но в тестах jsperf под Chrome 24 он был на пару порядков быстрее, чем любой другой метод на основе селектора jQuery.

Альнитак
источник
1
Мне нравится этот плагин, но есть 2 проблемы: 1) Сценарий плагина не может быть включен в заголовок, потому что document.bodyеще не инициализирован, 2) Производительность намного лучше, чем у альтернатив, если количество дочерних узлов очень велико. Только для нескольких детей (скажем, менее 10) $('>:first-child',context)это немного быстрее. На производительность влияет только количество детей, а не глубина.
код-фактор
Хороший вопрос о @codefactor document.body- я посмотрю на это.
Альнитак
4

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

$(this).children().first()
// is equivalent to
$(this.firstChild)
Yukulélé
источник
1

пожалуйста, используйте это, как это во-первых, дайте имя класса для тега p, как "myp"

затем используйте следующий код

$(document).ready(function() {
    $(".myp").click(function() {
        $(this).children(":first").toggleClass("classname"); // this will access the span.
    })
})
вишал гупта
источник
-3

Если вы хотите немедленного первого ребенка, вам нужно

    $(element).first();

Если вы хотите конкретный первый элемент в dom от вашего элемента, используйте ниже

    var spanElement = $(elementId).find(".redClass :first");
    $(spanElement).addClass("yourClassHere");

попробуйте: http://jsfiddle.net/vgGbc/2/

Амит Ратод
источник
11
это просто неправильно - если elementэто DOM-узел, то $(element).first()это эквивалентно $(element), а не его первому дочернему элементу.
Альнитак
1
Согласен, если элемент является DOM узел $ (элемент) .first () эквивалентно $ (элемент) , это вызвало проблемы меня с обязательным knockoutJS
drgn