Najlepszy sposób na uzyskanie węzłów potomnych

Zastanawiałem się, JavaScript oferuje wiele metod, aby uzyskać pierwszy element potomny z dowolnego elementu, ale który jest najlepszy? Przez best, mam na myśli: najbardziej kompatybilny między przeglądarkami, najszybszy, najbardziej wszechstronny i przewidywalny, jeśli chodzi o zachowanie. Lista metod / właściwości, których używam jako aliasów:

var elem = document.getElementById('container');
var child = elem.children[0];
var child = elem.firstElementChild; // == children[0]
To działa w obu przypadkach:]}
var child = elem.childNodes[0]; // or childNodes[1], see below

To w przypadku formularzy, lub <div> iteracji. Jeśli Mogę napotkać elementy tekstu:

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

As far as I can work out, firstChild używa NodeList z childNodes, a firstElementChild używa children. Oparłem to założenie na referencji MDN:

childNode jest odniesieniem do pierwszego elementu potomnego węzła elementu lub null, jeśli go nie ma.

Zgaduję, że jeśli chodzi o prędkość, różnica, jeśli w ogóle, będzie prawie niczym, ponieważ firstElementChild jest w rzeczywistości odniesieniem do children[0], a children obiekt i tak jest już w pamięci.

To, co mnie rzuca, to childNodes obiekt. Ja użyłem go do spojrzenia na formularz, w elemencie tabeli. Podczas gdy children wymienia wszystkie elementy formularza, childNodes wydaje się również zawierać białe znaki z kodu HTML:

console.log(elem.childNodes[0]);
console.log(elem.firstChild);

<TextNode textContent="\n ">

console.log(elem.childNodes[1]);
console.log(elem.children[0]);
console.log(elem.firstElementChild);

All log <input type="text"...>. Jak to? Rozumiem, że jeden obiekt pozwala mi pracować z "surowym" kodem HTML, podczas gdy drugi przykleja się do DOM, ale element childNodes wydaje się działać na obu poziomach.

Wracając do mojego początkowego pytania, domyślam się, że jeśli chcę najbardziej obiekt kompleksowy, childNodes jest drogą do zrobienia, ale ze względu na jego kompleksowość, może nie być najbardziej przewidywalny pod względem zwracania elementu, którego chcę/oczekuję w danym momencie. Obsługa między przeglądarkami może również okazać się wyzwaniem w tym przypadku, chociaż mogę się mylić.

Czy ktoś mógłby wyjaśnić różnicę między przedmiotami pod ręką? Jeśli jest różnica prędkości, jakkolwiek znikoma, też chciałbym wiedzieć. Jeśli widzę to wszystko źle, nie krępuj się edukować ja.


PS: Proszę, proszę, Lubię JavaScript, więc tak, chcę się tym zajmować. Odpowiedzi typu "jQuery zajmuje się tym dla Ciebie" nie są tym, czego szukam, stąd nie jQuery tag.

Author: Xufox, 2012-04-30

5 answers

Chyba za dużo o tym myślisz. Zauważyłeś różnicę między childNodes a children, która polega na tym, że childNodes zawiera wszystkie węzły, w tym węzły tekstowe składające się wyłącznie z białych znaków, podczas gdy children jest zbiorem tylko węzłów potomnych, które są elementami. To wszystko.

Nie ma nic nieprzewidywalnego w żadnym zbiorze, chociaż należy pamiętać o kilku kwestiach:

  • IE childNodes podczas gdy inne przeglądarki robią
  • IE children podczas gdy inne przeglądarki mają tylko elementy

children, firstElementChild a przyjaciele są tylko wygodami, prezentując przefiltrowany widok na DOM ograniczony tylko do elementów.

 187
Author: Tim Down,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-12 08:25:41

FirstElementChild może nie być dostępny w IE

W IE

Moje rozwiązanie

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

To da firstchild nawet na IE

 22
Author: neu-rah,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-17 19:07:22

Sposobem cross browser jest użycie childNodes, aby uzyskać NodeList, a następnie zrobić tablicę wszystkich węzłów z 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/

Jest to szczególnie proste, jeśli używasz biblioteki narzędzi, takiej jak lodash :
/**
 * Return direct children elements.
 *
 * @param {HTMLElement}
 * @return {Array}
 */
function elementChildren (element) {
    return _.where(element.childNodes, {nodeType: 1});
}

Przyszłość:

Można używać querySelectorAll w połączeniu z :scope pseudo-Klasa (pasuje do elementu, który jest punktem odniesienia w "selektor": {]}

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

W momencie pisania tego :scope jest obsługiwana W Chrome, Firefox i Safari.

 15
Author: Gajus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-20 09:06:24

Nie dajcie się zwieść białym przestrzeniom. po prostu przetestuj to w przeglądarce konsoli. użyj natywnego javascript. Oto i przykład z dwoma zestawami 'ul' z tą samą klasą. Nie musisz mieć listy' ul ' w jednej linii, aby uniknąć białych spacji, po prostu użyj tablicy, aby przeskoczyć nad białymi spacjami.

Jak ominąć białą spację za pomocą querySelector() wtedy 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>
 1
Author: andre paradise,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-27 07:01:56

Aby dodać do innych odpowiedzi, nadal istnieją godne uwagi różnice, szczególnie w przypadku elementów <svg>.

Używałem zarówno .childNodes jak i .children i wolałem pracować z HTMLCollection dostarczanym przez getter .children.

Dzisiaj jednak natknąłem się na problemy z IE/Edge podczas używania .children na <svg>. Chociaż .children jest obsługiwany w IE na podstawowych elementach HTML, nie jest obsługiwany na fragmentach dokumentu/dokumentu, lub elementach SVG.

Dla mnie, byłem w stanie po prostu pobrać potrzebne elementy przez .childNodes[n], ponieważ nie mam zbędnych węzłów tekstowych, którymi muszę się martwić. Możesz być w stanie zrobić to samo, ale jak wspomniano w innym miejscu powyżej, nie zapominaj, że możesz napotkać nieoczekiwane elementy.

Mam nadzieję, że jest to pomocne dla kogoś, kto drapie się po głowie, próbując dowiedzieć się, dlaczego .children działa gdzie indziej w swoim js na nowoczesnym IE i nie działa na elementach dokumentu lub SVG.

 0
Author: slothluvchunk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-21 17:44:57