Вопрос по dom, javascript – Лучший способ получить дочерние узлы

205

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

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

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

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

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

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

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

childNode is a reference to the first child element of the element node, or null if there isn’t one.

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

Что бросает меня, этоchildNodes объект. Я использовал его, чтобы взглянуть на форму в элементе таблицы. В то время какchildren перечисляет все элементы формы,childNodes также, кажется, включает пробелы из кода HTML:

<code>console.log(elem.childNodes[0]);
console.log(elem.firstChild);
</code>

Оба журнала<TextNode textContent="\n ">

<code>console.log(elem.childNodes[1]);
console.log(elem.children[0]);
console.log(elem.firstElementChild);
</code>

Весь журнал<input type="text"& # X2026;>, Как так? Я понимаю, что один объект позволил бы мне работать с & # x201C; raw & # x201D; HTML-код, в то время как другой придерживается DOM, ноchildNodes Элемент, кажется, работает на обоих уровнях.

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

Кто-нибудь может прояснить различие между предметами под рукой? Если есть разница в скорости, как бы она ни была незначительна, я тоже хотел бы знать. Если я все это вижу неправильно, не стесняйтесь обучать меня.

PS: Пожалуйста, пожалуйста, мне нравится JavaScript, так что да, я хочу иметь дело с такого рода вещами. Ответы типа & # x201C; jQuery справляется с этим для вас & # x201D; не то, что я ищу, следовательно, нет тег.

& GT; & GT; пожалуйста, пожалуйста, мне нравится JavaScript, так что да, я хочу иметь дело с такого рода вещами. ответы типа «jQuery справляется с этим для вас»; это не то, что я ищу & lt; голос за это david.barkhuizen
Я пришел сюда для простого способа получить дочерние узлы. Я не нашел ни одного. Я ушел. Andrew

Ваш Ответ

5   ответов
0

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

Я использовал оба.childNodes а также.children и предпочли работать сHTMLCollection доставлено.children добытчик.

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

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

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

195

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

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

  • IE <= 8 do not include white space-only text nodes in childNodes while other browsers do
  • IE <= 8 includes comment nodes within children while other browsers only have elements

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

Error: User Rate Limit Exceeded Elias Van Ootegem
Error: User Rate Limit ExceededchildrenError: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded<td\n\t>content</td>Error: User Rate Limit Exceeded Elias Van Ootegem
15

Кросс-браузерный способ это использоватьchildNodes получитьNodeList, а затем сделать массив всех узлов сnodeType ELEMENT_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/

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

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

F,uture:

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

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

На момент написания этого:scope is supported в Chrome, Firefox и Safari.

:scope was removed from the specError: User Rate Limit ExceededFutureError: User Rate Limit Exceeded
1

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

Как обойти пустое пространство сquerySelector() затемchildNodes[] JS Fiddle Link: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>
Error: User Rate Limit Exceededdocument.querySelectorError: User Rate Limit ExceededchildrenError: User Rate Limit ExceededchildNodes internallyError: User Rate Limit ExceededchildNodes doesError: User Rate Limit ExceededchildrenError: User Rate Limit Exceeded Elias Van Ootegem
21

firstElementChild может быть недоступен в IE & lt; 9 (только firstChild)

в IE & lt; 9 firstChild является firstElementChild, поскольку MS DOM (IE & lt; 9) не хранит пустые текстовые узлы. Но если вы сделаете это в других браузерах, они вернут пустые текстовые узлы ...

мое решение

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

это даст первому ребенку даже в IE & lt; 9

Error: User Rate Limit ExceededthisError: User Rate Limit Exceeded Elias Van Ootegem
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded Elias Van Ootegem
Error: User Rate Limit Exceededelem.firstChildError: User Rate Limit Exceededelem.firstElementChildError: User Rate Limit Exceeded
firstElementChildError: User Rate Limit Exceeded

Похожие вопросы