Получить nth-дочерний номер элемента в чистом JavaScript

Я создаю функцию для своего сайта, где я устанавливаю атрибут данных, который содержит nth-дочерний номер этого элемента.

моя разметка HTML:

<html>
<body>
    <section class="hardware">some text, nth-child is one</section>
    <section class="hardware">some text, nth-child is two</section>
    <section class="hardware">some text, nth-child is three</section>
    <section class="hardware">some text, nth-child is four</section>
    <section class="hardware">some text, nth-child is five</section>
</body>
</html>

мой JavaScript до сих пор:

var selector = document.getElementsByClassName('hardware');
for(var i = 0; i <= selector.length; i++) {
    var index = selector[i] //get the nth-child number here
    selector[i].dataset.number = index;
}

Как я могу получить N-й дочерний номер элемента с чистым JavaScript (не jQuery), это возможно даже в JavaScript?

5 ответов


когда вы говорите "число", Вы имеете в виду 1, 2 и т. д. или" один"," два " и т. д.?

Если 1, 2 и т. д., то число просто i+1...

Если "один", "два" и т. д., то вам нужно получить текст внутри элемента, а затем использовать регулярное выражение, чтобы разобрать его и получить нужное значение.


проверьте этот предыдущий ответ здесь.

Он использует

var i = 0;
while( (child = child.previousSibling) != null ) 
  i++;
//at the end i will contain the index.

Я собираюсь ответить на вопросы со следующими предположениями:

  • код hardware классифицировать элементы все братья
  • вас интересует nth ребенок не nth ребенок + 1
  • их можно смешать с другими элементами:
<body>
    <section class="hardware">some text, nth-child is zero</section>
    <section class="software"></section>
    <section class="hardware">some text, nth-child is two</section>
</body>

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

таким образом, основное отличие заключается в том, что вместо запроса элементов, которые принадлежите к данному классу, я собираюсь получить (прямые) дети body, и фильтровать их.

Array.from(document.body.children)
  .map((element, index) => ({element, index}))
  .filter(({element}) => element.classList.contains('hardware'))

результирующий массив будет выглядеть так:

[
  {element: section.hardware, index: 0}
  {element: section.hardware, index: 2}
]

просто приращение индекса линейно будет работать, только если все элементы, соответствующие этому имени класса, являются единственными дочерними элементами одного и того же родителя, без других элементов, которые могут мешать :nth-child(), как показано точно в данной разметке. См.ответ для объяснения того, как другие элементы могут вмешиваться. Также просмотрите селекторы spec on :nth-child().

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

var selector = document.getElementsByClassName('hardware');

for (var i = 0; i < selector.length; i++) {
    var element = selector[i];
    var child = element.parentNode.firstChild;
    var index = 0;

    while (true) {
        if (child.nodeType === Node.ELEMENT_NODE) {
            index++;
        }

        if (child === element || !child.nextSibling) {
            break;
        }

        child = child.nextSibling;
    }

    element.dataset.number = index;
}

демо JSFiddle

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

  • если конкретный section.hardware элемент является первым и единственным дочерним элементом другого section будет присвоен правильный индекс 1.

  • если .hardware элемент является вторым дочерним элементом своего родителя, даже если он единственный с этим классом (т. е. он следует за каким-то другим элементом без класс), ему будет присвоен правильный индекс 2.


вы можете разделить текст на пробелы в get The last слово из каждого разделенного массива:

var hards = document.getElementsByClassName('hardware');
for (var i=0; i < hards.length; i++) {
    var hardText = hards[i].innerText || hard[i].textContent;
    var hardList = hardText.split(' ');
    var hardLast = hardList[hardList.length - 1];
    alert(hardLast);
}

я использую || здесь, потому что Firefox не поддерживает innerText, в то время как IE не поддерживает textContent.

если элементы содержат только текст, то innerHTML может использоваться вместо innerText/textContent.