Получить элемент внутри элемента по классу и идентификатору - JavaScript

136

Хорошо, я пробовал себя в JavaScript раньше, но самое полезное, что я написал, это переключатель стилей CSS. Так что я немного новичок в этом. Допустим, у меня есть HTML-код вроде этого:

<div id="foo">
    <div class="bar">
        Hello world!
    </div>
</div>

Как бы я изменил "Привет, мир!" в "Прощай, мир!" ? Я знаю, как работают document.getElementByClass и document.getElementById, но я бы хотел получить более конкретную информацию. Извините, если об этом уже спрашивали.

Тэннер Бэбкок
источник

Ответы:

233

Ну, во-первых, вам нужно выбрать элементы с помощью функции, как getElementById.

var targetDiv = document.getElementById("foo").getElementsByClassName("bar")[0];

getElementByIdвозвращает только один узел, но getElementsByClassNameвозвращает список узлов. Поскольку существует только один элемент с таким именем класса (насколько я могу судить), вы можете просто получить первый (для этого и нужен [0]- он похож на массив).

Затем вы можете изменить HTML с .textContent.

targetDiv.textContent = "Goodbye world!";

var targetDiv = document.getElementById("foo").getElementsByClassName("bar")[0];
targetDiv.textContent = "Goodbye world!";
<div id="foo">
    <div class="bar">
        Hello world!
    </div>
</div>

Джозеф Марикл
источник
1
Получение родителя по идентификатору в этом случае не требуется. document.getElementsByClassNameбудет работать нормально.
rvighne
7
@rvighne точные требования ОП заключались в том, что он «хотел бы получить более конкретные». Человек, задающий вопрос, спрашивал, как он может быть более конкретным в своем обходе дерева DOM. Использование getElementByClassName не приводило к путанице, но я вижу, как кто-то может легко подумать, что я указывал на то и другое по мере необходимости. Они не. Если вы хотите настроить таргетинг только на элементы определенного класса, которые находятся под конкретным узлом данного идентификатора, а не на элементы этого же класса под другим узлом, это то, что вы бы использовали.
Джозеф Марикль
1
Возможно, будет полезно отредактировать этот ответ и перейти .innerHtmlна него .textContentдля обеспечения безопасности кодеров копирования / вставки.
codescribblr
14

Вы можете сделать это так:

var list = document.getElementById("foo").getElementsByClassName("bar");
if (list && list.length > 0) {
    list[0].innerHTML = "Goodbye world!";
}

или, если вы хотите сделать это с меньшей проверкой ошибок и большей краткостью, это можно сделать в одну строку следующим образом:

document.getElementById("foo").getElementsByClassName("bar")[0].innerHTML = "Goodbye world!";

По объяснению:

  1. Вы получаете элемент с id="foo" .
  2. Затем вы найдете объекты, которые содержатся в этом объекте, которые имеют class="bar" .
  3. Это возвращает массив-подобный nodeList, так что вы ссылаетесь на первый элемент в этом nodeList
  4. Затем вы можете установить innerHTMLэтот элемент, чтобы изменить его содержимое.

Предостережения: некоторые старые браузеры не поддерживают getElementsByClassName(например, старые версии IE). Эта функция может быть вставлена ​​на место, если она отсутствует.


Именно здесь я рекомендую использовать библиотеку, которая имеет встроенную поддержку селектора CSS3, а не беспокоиться о совместимости браузера самостоятельно (пусть кто-то другой сделает всю работу). Если вам нужна библиотека, то Sizzle будет отлично работать. В Sizzle это будет сделано так:

Sizzle("#foo .bar")[0].innerHTML = "Goodbye world!";

jQuery имеет встроенную библиотеку Sizzle, а в jQuery это будет:

$("#foo .bar").html("Goodbye world!");
jfriend00
источник
Спасибо, у меня были проблемы с document.getElementBy *. JQuery делает вещи намного проще.
Тэннер Бэбкок
7

Если это должно работать в IE 7 или ниже, вы должны помнить, что getElementsByClassName существует не во всех браузерах. Из-за этого вы можете создать свой собственный getElementsByClassName или вы можете попробовать это.

var fooDiv = document.getElementById("foo");

for (var i = 0, childNode; i <= fooDiv.childNodes.length; i ++) {
    childNode = fooDiv.childNodes[i];
    if (/bar/.test(childNode.className)) {
        childNode.innerHTML = "Goodbye world!";
    }
}
Джон Хартсок
источник
getElementsByClassNameтоже не работает в IE8, но вы можете использовать querySelectorAllего вместо него (в любом случае).
user113716
@ Ӫ _._ Ӫ ... лол ... ты прав, но ты просто докажи мой ответ еще больше. Вы не можете полагаться на getElementsByClassName, если ваша страница должна работать в нескольких браузерах. JQuery определенно будет вариант, но так же, как приведенный выше код.
Джон Хартсок
Да, я имел в виду этот комментарий в поддержку вашего ответа, но также и для указания на то, что его можно использовать qSAв шимме, чтобы вы все еще могли использовать собственный код в IE8. Хотя при более внимательном рассмотрении вашего решения у вас есть несколько вещей, которые необходимо исправить.
user113716
@ Ӫ _._ Ӫ ... интересно, что ты видишь ... потому что я этого не вижу.
Джон Хартсок
var i = 0, var child = fooDiv.childNodes[i]является недействительным. i <= fooDiv.childNodesна самом деле не имеет смысла. childNode.className.test("bar")Там нет childNodeпеременной, и у строки нет test()метода.
user113716
4

Рекурсивная функция:

function getElementInsideElement(baseElement, wantedElementID) {
    var elementToReturn;
    for (var i = 0; i < baseElement.childNodes.length; i++) {
        elementToReturn = baseElement.childNodes[i];
        if (elementToReturn.id == wantedElementID) {
            return elementToReturn;
        } else {
            return getElementInsideElement(elementToReturn, wantedElementID);
        }
    }
}
Ави Шимшилашвили
источник
В приведенном выше примере есть небольшая ошибка. Вместо того, чтобы мгновенно возвращаться по другому пути, вы должны проверить, было ли что-то найдено первым. В противном случае другие дочерние узлы не будут зациклены. Примерно так: if (elementToReturn) {return elementToReturn; }
Jannik
3

Самый простой способ сделать это:

function findChild(idOfElement, idOfChild){
  let element = document.getElementById(idOfElement);
  return element.querySelector('[id=' + idOfChild + ']');
}

или лучше читаемый:

findChild = (idOfElement, idOfChild) => {
    let element = document.getElementById(idOfElement);
    return element.querySelector(`[id=${idOfChild}]`);
}
Бенджамин Вернер
источник
-4

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

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>                                                                                                             
<div id="foo">
   <div class="bar"> 
          Hello world!
     </div>
</div>

использовать это :

$("[id^='foo']").find("[class^='bar']")

// do not forget to add script tags as above

если вы хотите удалить, отредактируйте любую операцию, затем просто добавьте "." позади и делать операции

хардик акбари
источник
10
Использование термоядерного оружия, чтобы убить оленя, будет работать, но немного излишним. Использование библиотеки jQuery размером в несколько килобайт для выбора элемента, когда Javascript предлагает эту функциональность в его базовом коде, немного более излишним.
Данежир