Лучший способ получить дочерние узлы


мне было интересно, JavaScript предлагает множество методов для получения первого дочернего элемента из любого элемента, но какой из них лучше? Лучше всего, я имею в виду: наиболее кросс-браузер совместим, быстрый, наиболее полный и предсказуемый, когда речь заходит о поведении. Список методов / свойств, которые я использую в качестве псевдонимов:

var elem = document.getElementById('container');
var child = elem.children[0];
var child = elem.firstElementChild; // == children[0]

это работает в обоих случаях:

var child = elem.childNodes[0]; // or childNodes[1], see below

это в случае форм, или <div> итерации. Если я могу столкнуться с текстом элементы:

var child = elem.childNodes; // treat as NodeList
var child = elem.firstChild;

насколько я могу понять,firstChild использует список узлов из childNodes и firstElementChild использует children. Я основываю это предположение на ссылке MDN:

childNode ссылка на первый дочерний элемент элемента, или null если нет.

я предполагаю, что с точки зрения скорости разница, если таковая имеется, будет почти нулевой, так как firstElementChild фактически является ссылкой на children[0], и элемент children объект уже в памяти в любом случае.

что меня бросает, так это

5 199

5 ответов:

Похоже, ты слишком много думаешь. Вы заметили разницу между childNodes и children, что childNodes содержит все узлы, включая текстовые узлы, состоящие целиком из пробелов, в то время как children представляет собой набор только дочерних узлов, которые являются элементами. Это действительно все, что нужно.

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

  • IE childNodes в то время как другие браузеры делают
  • IE children в то время как другие браузеры имеют только элементы

children,firstElementChild и друзья-это просто удобства, представляющие отфильтрованный вид DOM, ограниченный только элементами.

firstElementChild может быть недоступен в IE

на IE

мое решение

child=(elem.firstElementChild||elem.firstChild)

это даст первенца даже на IE

кросс-браузер способ сделать это использовать childNodes и NodeList, потом сделать массив всех узлов с nodeTypeELEMENT_NODE.

/**
 * Return direct children elements.
 *
 * @param {HTMLElement}
 * @return {Array}
 */
function elementChildren (element) {
    var childNodes = element.childNodes,
        children = [],
        i = childNodes.length;

    while (i--) {
        if (childNodes[i].nodeType == 1) {
            children.unshift(childNodes[i]);
        }
    }

    return children;
}

http://jsfiddle.net/s4kxnahu/

это особенно легко, если вы используете служебную библиотеку, такую как лодашь:

/**
 * Return direct children elements.
 *
 * @param {HTMLElement}
 * @return {Array}
 */
function elementChildren (element) {
    return _.where(element.childNodes, {nodeType: 1});
}

будущее:

можно использовать querySelectorAll в сочетании с :scope псевдо-класса (соответствует элементу, который является опорной точкой селектора):

parentElement.querySelectorAll(':scope > *');

на момент написания этого :scope поддерживает в Chrome, Firefox и Safari.

- Эй, ребята, не позволяйте обмануть белого пространства. просто проверьте это в браузере консоли. используйте собственный javascript. Вот и пример с двумя наборами ' ul ' с одним и тем же классом. Вам не нужно иметь свой список " ul " в одной строке, чтобы избежать пробелов, просто используйте свой счетчик массивов, чтобы перепрыгнуть через пробел.

как обойти пробел, с querySelector() затем childNodes[] JS скрипка Ссылка:https://jsfiddle.net/aparadise/56njekdo/

var y = document.querySelector('.list');
var myNode = y.childNodes[11].style.backgroundColor='red';

<ul class="list">
    <li>8</li>
    <li>9</li>
    <li>100</li>
</ul>

<ul class="list">
    <li>ABC</li>
    <li>DEF</li>
    <li>XYZ</li>
</ul>

просто чтобы добавить к другим ответам, здесь все еще есть примечательные различия, особенно при работе с <svg> элементы.

я использовал как .childNodes и .children и предпочли работать с HTMLCollection выступил .children геттер.

однако сегодня я столкнулся с проблемами с IE / Edge при использовании.children на <svg>. В то время как .children поддерживается в IE на основных элементах HTML,он не поддерживается в документе / документе фрагменты, или SVG elements.

для меня, я был в состоянии просто взять нужные элементы через .childNodes[n] потому что у меня нет внешних текстовых узлов для беспокойства. Вы можете быть в состоянии сделать то же самое, но как уже упоминалось выше, не забывайте, что вы можете столкнуться с неожиданными элементами.

надеюсь, что это полезно для кого-то ломают головы, пытаясь выяснить, почему .children работает в другом месте в их js на современном IE и терпит неудачу на документе или SVG элементов.