Pobierz element wewnątrz elementu według klasy i identyfikatora - JavaScript


136

W porządku, wcześniej parałem się JavaScript, ale najbardziej użyteczną rzeczą, jaką napisałem, jest przełącznik stylów CSS. Więc jestem w tym trochę nowy. Powiedzmy, że mam taki kod HTML:

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

Jak zmieniłbym „Hello world!” do „Goodbye world!” ? Wiem, jak działają dokumenty document.getElementByClass i document.getElementById, ale chciałbym uzyskać bardziej szczegółowe informacje. Przepraszamy, jeśli o to pytano wcześniej.

Odpowiedzi:


232

Cóż, najpierw musisz wybrać elementy z funkcją taką jak getElementById.

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

getElementByIdzwraca tylko jeden węzeł, ale getElementsByClassNamezwraca listę węzłów. Ponieważ istnieje tylko jeden element o tej nazwie klasy (o ile wiem), możesz po prostu pobrać pierwszy (do tego [0]służy - to jak tablica).

Następnie możesz zmienić kod HTML za pomocą .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
W tym przypadku nie jest konieczne uzyskanie dowodu tożsamości rodzica. document.getElementsByClassNamebędzie działać dobrze.
rvighne

7
@rvighne dokładne wymagania OP były takie, że „chciałby uzyskać bardziej szczegółowe informacje”. Osoba zadająca pytanie pytała, w jaki sposób mógłby być bardziej szczegółowy w przechodzeniu przez drzewo DOM. Użycie metody getElementByClassName nie było powodem do zamieszania, ale widzę, jak ktoś może łatwo pomyśleć, że wskazuję oba jako konieczne. Oni nie są. Jeśli chcesz kierować reklamy tylko na elementy określonej klasy, które znajdują się w określonym węźle o danym identyfikatorze, w przeciwieństwie do elementów tej samej klasy w innym węźle, to właśnie tego powinieneś użyć.
Joseph Marikle

1
Dobrze byłoby wyedytować tę odpowiedź i zmienić .innerHtml.textContentna ze względu na bezpieczeństwo koderów kopiuj / wklej.
Codescribblr

14

Możesz to zrobić w ten sposób:

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

lub, jeśli chcesz to zrobić z mniejszą ilością sprawdzania błędów i większą zwięzłością, możesz to zrobić w jednej linii, jak poniżej:

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

W wyjaśnieniu:

  1. Dostajesz element z id="foo".
  2. Następnie znajdziesz obiekty zawarte w tym obiekcie, które mają class="bar".
  3. To zwraca tablicę nodeList, więc odwołujesz się do pierwszego elementu w tej nodeList
  4. Następnie możesz ustawić innerHTMLten element, aby zmienić jego zawartość.

Ostrzeżenia: niektóre starsze przeglądarki nie obsługują getElementsByClassName(np. Starsze wersje IE). Jeśli brakuje tej funkcji, można ją ustawić na miejscu.


W tym miejscu zalecam korzystanie z biblioteki, która ma wbudowaną obsługę selektora CSS3, zamiast martwić się o zgodność przeglądarki samodzielnie (niech ktoś inny wykona całą pracę). Jeśli chcesz, aby robiła to tylko biblioteka, Sizzle będzie działać świetnie. W Sizzle byłoby to zrobione w ten sposób:

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

jQuery ma wbudowaną bibliotekę Sizzle, aw jQuery wyglądałoby to tak:

$("#foo .bar").html("Goodbye world!");

Dziękuję, miałem problem z document.getElementBy *. jQuery sprawia, że ​​wszystko jest o wiele łatwiejsze.
Tanner Babcock

7

Jeśli ma to działać w przeglądarce IE 7 lub starszej, należy pamiętać, że metoda getElementsByClassName nie istnieje we wszystkich przeglądarkach. Z tego powodu możesz stworzyć własne getElementsByClassName lub spróbować tego.

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!";
    }
}

getElementsByClassNamenie działa również w IE8, ale możesz użyć querySelectorAllgo zamiast niego (prawie tak).
user113716

@ Ӫ _._ Ӫ ... lol ... masz rację, ale po prostu udowodniłeś moją odpowiedź jeszcze bardziej. Nie możesz polegać na getElementsByClassName, jeśli Twoja strona musi działać w wielu przeglądarkach. jQuery z pewnością byłoby opcją, ale tak samo jak powyższy kod.
John Hartsock,

Tak, miałem na myśli ten komentarz na poparcie twojej odpowiedzi, ale także po to, aby wskazać, że można użyć qSApodkładki, aby nadal można było używać natywnego kodu w IE8. Chociaż przyjrzymy się bliżej rozwiązaniu, jest kilka rzeczy, które wymagają naprawy.
user113716

@ Ӫ _._ Ӫ ... ciekawy, co widzisz ... bo ja tego nie widzę.
John Hartsock,

var i = 0, var child = fooDiv.childNodes[i]jest nieważny. i <= fooDiv.childNodesnie ma sensu. childNode.className.test("bar")Nie ma childNodezmiennej, a łańcuch nie ma test()metody.
user113716

4

Funkcja rekurencyjna:

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);
        }
    }
}

Powyższa próbka zawiera drobny błąd. Zamiast natychmiast wracać na inną ścieżkę, musisz najpierw sprawdzić, czy coś zostało znalezione. W przeciwnym razie inne węzły potomne nie zostaną przelane. Coś takiego: if (elementToReturn) {return elementToReturn; }
Jannik

3

Najłatwiej to zrobić:

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

lub lepiej czytelny:

findChild = (idOfElement, idOfChild) => {
    let element = document.getElementById(idOfElement);
    return element.querySelector(`[id=${idOfChild}]`);
}

-4

Nie powinieneś używać document.getElementByID, ponieważ działa on tylko dla kontrolek po stronie klienta, których identyfikatory są naprawione. Zamiast tego powinieneś użyć jquery, jak na poniższym przykładzie.

<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>

Użyj tego :

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

// do not forget to add script tags as above

jeśli chcesz usunąć edycję dowolnej operacji, po prostu dodaj „.” za i wykonaj operacje


10
Użycie broni termojądrowej do zabicia jelenia zadziała, ale jest lekką przesadą. Używanie biblioteki jQuery o wielu kb do wybrania elementu, gdy JavaScript oferuje taką funkcjonalność w swoim kodzie podstawowym, jest nieco przesadą.
Danejir,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.