Zastanawiałem się, JavaScript oferuje wiele metod uzyskania pierwszego elementu potomnego z dowolnego elementu, ale który jest najlepszy? Mówiąc najlepiej, mam na myśli: najbardziej zgodny z wieloma 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]
Działa to w obu przypadkach:
var child = elem.childNodes[0]; // or childNodes[1], see below
Tak jest w przypadku formularzy lub <div>
iteracji. Jeśli mogę napotkać elementy tekstowe:
var child = elem.childNodes; // treat as NodeList
var child = elem.firstChild;
O ile mogę wypracować, firstChild
używa NodeList childNodes
i firstElementChild
używa children
. Opieram to założenie na referencji MDN:
childNode
jest odniesieniem do pierwszego elementu potomnego węzła elementu lubnull
jeśli go nie ma.
Zgaduję, że pod względem prędkości różnica, jeśli w ogóle, będzie prawie zerowa, ponieważ firstElementChild
jest to faktycznie odniesienie children[0]
, a children
obiekt i tak jest już w pamięci.
To, co mnie rzuca, to childNodes
przedmiot. Użyłem go, aby spojrzeć na formularz w elemencie tabeli. Chociaż children
wyświetla listę wszystkich elementów formularza, childNodes
wydaje się, że zawiera również spacje z kodu HTML:
console.log(elem.childNodes[0]);
console.log(elem.firstChild);
Oba dzienniki <TextNode textContent="\n ">
console.log(elem.childNodes[1]);
console.log(elem.children[0]);
console.log(elem.firstElementChild);
Wszystko dziennika <input type="text"
... >
. Dlaczego? Zrozumiałbym, że jeden obiekt pozwoliłby mi pracować z „surowym” kodem HTML, podczas gdy drugi przykleja się do DOM, ale childNodes
element wydaje się działać na obu poziomach.
Wracając do mojego początkowego pytania, domyślam się: jeśli chcę najbardziej kompleksowy obiekt, childNodes
jest to droga, ale ze względu na jego kompleksowość może nie być najbardziej przewidywalny pod względem zwrotu elementu, który chcę / oczekuj w dowolnym momencie. Wsparcie w różnych przeglądarkach może również okazać się wyzwaniem, chociaż mogę się mylić.
Czy ktoś mógłby wyjaśnić różnicę między przedmiotami? Jeśli jest różnica prędkości, choć nieznaczna, też chciałbym wiedzieć. Jeśli widzę, że to wszystko źle, nie krępuj się mnie uczyć.
PS: Proszę, lubię JavaScript, więc tak, chcę poradzić sobie z tego rodzaju sprawami. Odpowiedzi typu „jQuery zajmuje się tym dla Ciebie” nie są tym, czego szukam, dlatego niejquery etykietka.
źródło
Odpowiedzi:
Wygląda na to, że przesadzasz. Zauważyłeś różnicę między
childNodes
ichildren
, którachildNodes
zawiera wszystkie węzły, w tym węzły tekstowe składające się wyłącznie z białych znaków, podczas gdychildren
jest to zbiór tylko węzłów potomnych, które są elementami. To naprawdę wszystko.Nie ma nic nieprzewidywalnego w żadnej z tych kolekcji, choć należy pamiętać o kilku kwestiach:
childNodes
podczas gdy inne przeglądarki to robiąchildren
podczas gdy inne przeglądarki mają tylko elementychildren
,firstElementChild
a znajomi to tylko wygody, prezentujące odfiltrowany widok DOM ograniczony tylko do elementów.źródło
<td\n\t>content</td>
. Tak jak w przypadku XML, aby uniknąć traktowania nadmiaru białych znaków jako części danych (w tym przypadku DOM). Dlaczego spacje wewnątrz tagu powinny być uwzględnione w DOM?children
powstał on w IE 4 ponad dekadę, zanim stał się standardem lub został przyjęty przez inne przeglądarki, możesz argumentować, że IE <= 8 jest poprawny, a inne przeglądarki są błędne.firstElementChild może być niedostępny w IE <9 (tylko firstChild)
w IE <9 firstChild jest firstElementChild, ponieważ MS DOM (IE <9) nie przechowuje pustych węzłów tekstowych. Ale jeśli zrobisz to w innych przeglądarkach, zwrócą puste węzły tekstowe ...
moje rozwiązanie
child=(elem.firstElementChild||elem.firstChild)
da to pierwszemu dziecku nawet w IE <9
źródło
elem.firstChild
nie jest węzłem elementu, wyniki będą inne w starych IE, ponieważelem.firstElementChild
zawsze jest węzłem elementu.firstElementChild
niekoniecznie jest również bezpieczny w przeglądarkach innych niż IE: Firefox zaczął obsługiwać go tylko w wersji 3.5.Można to zrobić za pomocą przeglądarki,
childNodes
aby uzyskaćNodeList
, a następnie utworzyć tablicę wszystkich węzłów za pomocąnodeType
ELEMENT_NODE .http://jsfiddle.net/s4kxnahu/
Jest to szczególnie łatwe, jeśli używasz biblioteki narzędziowej, takiej jak lodash :
Przyszłość:
Możesz używać
querySelectorAll
w połączeniu z:scope
pseudoklasą (pasuje do elementu, który jest punktem odniesienia selektora):W momencie pisania tego
:scope
jest obsługiwany w Chrome, Firefox i Safari.źródło
Aby dodać do innych odpowiedzi, nadal istnieją tutaj istotne różnice, szczególnie w przypadku
<svg>
elementów.Użyłem obu
.childNodes
i.children
wolałem pracować zHTMLCollection
dostarczonym przez.children
gettera.Jednak dzisiaj napotkałem problemy z awarią IE / Edge podczas korzystania
.children
z<svg>
. Chociaż.children
jest obsługiwany w IE w podstawowych elementach HTML, nie jest obsługiwany w dokumentach / fragmentach dokumentów ani elementach SVG .Dla mnie byłem w stanie po prostu pobrać potrzebne elementy,
.childNodes[n]
ponieważ nie muszę się martwić dodatkowymi węzłami tekstowymi. Możesz zrobić to samo, ale jak wspomniano 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, a zawiesza elementy dokumentu lub SVG.źródło
Hej, chłopaki, nie dajcie się zwieść białej przestrzeni. po prostu przetestuj to w przeglądarce konsoli. użyj natywnego javascript. Oto i przykład z dwoma zestawami „ul” o tej samej klasie. Nie musisz mieć listy „ul” w jednym wierszu, aby uniknąć spacji, po prostu użyj liczby tablic, aby przeskoczyć nad białą spacją.
Jak ominąć białą przestrzeń
querySelector()
następniechildNodes[]
js skrzypce link: https://jsfiddle.net/aparadise/56njekdo/źródło
document.querySelector
nie było wtedy dobrze poparte. b) Pytanie polega w zasadzie na zadaniu różnic między wewnętrznymichildren
ichildNodes
wewnętrznymi , co jest bardziej wiarygodne, kiedy wybrać jedną z drugiej. oraz c) Ponieważ, jak demonstraded w pytaniu:childNodes
czy to odstępy węzłów,children
nie ...