В чем разница между дочерними и дочерними узлами в JavaScript?

305

Я нашел себя , используя JavaScript и я натыкался childNodesи childrenсвойства. Мне интересно, в чем разница между ними. Также один предпочтительнее другого?

Джон
источник

Ответы:

330

Поймите, что .childrenэто свойство элемента . 1 Только элементы имеют .children, и все эти потомки имеют тип элемента. 2

Тем не менее, .childNodesявляется собственностью узла . .childNodesможет содержать любой узел. 3

Конкретный пример будет:

let el = document.createElement("div");
el.textContent = "foo";

el.childNodes.length === 1; // Contains a Text node child.
el.children.length === 0;   // No Element children.

Большую часть времени вы хотите использовать, .childrenпотому что обычно вы не хотите зацикливаться на узлах Text или Comment при манипуляциях с DOM.

Если вы хотите манипулировать текстовыми узлами, вы, вероятно, хотите .textContentвместо этого. 4


1. Технически, это атрибут ParentNode , миксина , включенного в Element.
2. Все они являются элементами, потому что .childrenэто HTMLCollection , которая может содержать только элементы.
3. Аналогично, .childNodesможет содержать любой узел, потому что это NodeList .
4. Или .innerText. Смотрите различия здесь или здесь .

Raynos
источник
3
Да, у IE, похоже, есть некоторые проблемы: quirksmode.org/dom/w3c_core.html#t71
Феликс Клинг
4
На самом деле children - это свойство интерфейса parentnode, а не элемента. usonsci.wordpress.com/2014/09/30/html-children-vs-childnodes
победитель
Кажется, iOS 8.3 (может быть, другие?) Не поддерживает .childrenXML-документы : jsfiddle.net/fbwbjvch/1
Saebekassebil
4
Были проблемы только с Microsoft Edge с узлами XML. Похоже, Microsoft Edge не любит детей. Это хорошо, я бы не хотел, чтобы этот браузер воспроизводил.
Дан-Нолан
1
Естественное продолжение «элемент против узла»: stackoverflow.com/questions/132564/…
user1454265
23

Element.childrenвозвращает только дочерние элементы , а Node.childNodesвозвращает все дочерние узлы . Обратите внимание, что элементы являются узлами, поэтому оба элемента доступны для элементов.

Я считаю childNodesболее надежным. Например, MDC (ссылка выше) отмечает, что IE получил childrenправа только в IE 9. childNodesПредоставляет меньше возможностей для ошибок разработчикам браузеров.

Мэтью Флэшен
источник
2
Черт возьми, если бы только это работало на IE 6-8, это была бы мечта.
Ry-
3
@minitech это работает (для некоторой ценности работы). Очевидно .children, не отфильтровывает узлы комментариев, но отфильтровывает текстовые узлы.
Рейнос
2
@Raynos: Точно - то же самое с .getElementsByTagName('*'). IE может иногда быть таким раздражающим ...
Ry-
Существуют реализации shim / polyfill, childrenкоторые поддерживают IE.
wrlee
7

Хорошие ответы до сих пор, я хочу только добавить, что вы можете проверить тип узла, используя nodeType:

yourElement.nodeType

Это даст вам целое число: (взято отсюда )

| Value |             Constant             |                          Description                          |  |
|-------|----------------------------------|---------------------------------------------------------------|--|
|    1  | Node.ELEMENT_NODE                | An Element node such as <p> or <div>.                         |  |
|    2  | Node.ATTRIBUTE_NODE              | An Attribute of an Element. The element attributes            |  |
|       |                                  | are no longer implementing the Node interface in              |  |
|       |                                  | DOM4 specification.                                           |  |
|    3  | Node.TEXT_NODE                   | The actual Text of Element or Attr.                           |  |
|    4  | Node.CDATA_SECTION_NODE          | A CDATASection.                                               |  |
|    5  | Node.ENTITY_REFERENCE_NODE       | An XML Entity Reference node. Removed in DOM4 specification.  |  |
|    6  | Node.ENTITY_NODE                 | An XML <!ENTITY ...> node. Removed in DOM4 specification.     |  |
|    7  | Node.PROCESSING_INSTRUCTION_NODE | A ProcessingInstruction of an XML document                    |  |
|       |                                  | such as <?xml-stylesheet ... ?> declaration.                  |  |
|    8  | Node.COMMENT_NODE                | A Comment node.                                               |  |
|    9  | Node.DOCUMENT_NODE               | A Document node.                                              |  |
|   10  | Node.DOCUMENT_TYPE_NODE          | A DocumentType node e.g. <!DOCTYPE html> for HTML5 documents. |  |
|   11  | Node.DOCUMENT_FRAGMENT_NODE      | A DocumentFragment node.                                      |  |
|   12  | Node.NOTATION_NODE               | An XML <!NOTATION ...> node. Removed in DOM4 specification.   |  |

Обратите внимание, что в соответствии с Mozilla :

Следующие константы устарели и больше не должны использоваться: Node.ATTRIBUTE_NODE, Node.ENTITY_REFERENCE_NODE, Node.ENTITY_NODE, Node.NOTATION_NODE

Чаба
источник
0

Выберите один зависит от метода, который вы ищете !?

Я пойду с ParentNode.children :

Так как он предоставляет namedItemметод, который позволяет мне напрямую получить один из дочерних элементов, не просматривая все дочерние элементы или избегая использования getElementByIdи т. Д.

например

ParentNode.children.namedItem('ChildElement-ID'); // JS
ref.current.children.namedItem('ChildElement-ID'); // React
this.$refs.ref.children.namedItem('ChildElement-ID'); // Vue

Я пойду с Node.childNodes :

Как это обеспечивает forEachметод, когда я работаю с, window.IntersectionObserver например,

nodeList.forEach((node) => { observer.observe(node) })
// IE11 does not support forEach on nodeList, but easy to be polyfilled.

На Chrome 83

Node.childNodes обеспечивает entries, forEach, item, keys, lengthиvalues

ParentNode.children обеспечивает item, lengthиnamedItem

Макс Ма
источник