รับองค์ประกอบภายในองค์ประกอบตามคลาสและ ID - JavaScript


143

เอาล่ะฉันเคยขลุกอยู่กับ JavaScript มาก่อน แต่สิ่งที่มีประโยชน์ที่สุดที่ฉันเขียนคือ CSS style-switcher ดังนั้นฉันค่อนข้างใหม่สำหรับเรื่องนี้ สมมติว่าฉันมีโค้ด HTML ดังนี้:

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

ฉันจะเปลี่ยนHello world!เป็นGoodbye world!อย่างไร

ฉันรู้วิธีdocument.getElementsByClassNameและdocument.getElementByIdการทำงาน แต่ฉันต้องการที่จะได้รับเฉพาะเจาะจงมากขึ้น ขออภัยหากมีการถามก่อนหน้านี้

คำตอบ:


247

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
ไม่จำเป็นต้องรับผู้ปกครองด้วย ID ในกรณีนี้ document.getElementsByClassNameจะทำงานได้ดี
rvighne

8
@rvighne ข้อกำหนดที่แน่นอนของ OP คือเขา "ต้องการเจาะจงมากขึ้น" ผู้ถามคำถามกำลังถามว่าเขาจะเจาะจงมากขึ้นในการข้ามต้นไม้ DOM ของเขาได้อย่างไร การใช้ getElementByClassName ไม่ใช่ประเด็นที่ทำให้เกิดความสับสน แต่ฉันสามารถเห็นได้ว่าใครบางคนอาจคิดว่าฉันระบุทั้งสองอย่างได้ง่ายตามความจำเป็น พวกเขาจะไม่. หากคุณต้องการกำหนดเป้าหมายเฉพาะองค์ประกอบของคลาสบางอย่างที่อยู่ภายใต้โหนดเฉพาะของ ID ที่กำหนดซึ่งตรงข้ามกับองค์ประกอบของคลาสเดียวกันภายใต้โหนดอื่นนี่คือสิ่งที่คุณจะใช้
Joseph Marikle

1
อาจเป็นการดีที่จะแก้ไขคำตอบนี้และเปลี่ยน.innerHtmlเป็น.textContentเพื่อประโยชน์ด้านความปลอดภัยของตัวคัดลอก / วางโค้ด
codecribblr

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

ขอบคุณฉันมีปัญหากับ document.getElementBy * jQuery ทำให้สิ่งต่างๆง่ายขึ้นมาก
Tanner Babcock

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 เป็นตัวเลือกที่แน่นอน แต่โค้ดข้างต้นจะเป็นอย่างไร
John Hartsock

ใช่ฉันหมายถึงความคิดเห็นนั้นเพื่อสนับสนุนคำตอบของคุณ แต่ก็ยังชี้ให้เห็นว่าเป็นไปได้ที่จะใช้qSAใน shim เพื่อให้คุณยังสามารถใช้โค้ดเนทีฟใน IE8 ได้ แม้ว่าจะพิจารณาวิธีแก้ปัญหาอย่างละเอียดถี่ถ้วน แต่คุณก็มีบางสิ่งที่ต้องแก้ไข
user113716

@ Ӫ _._ Ӫ ... อยากรู้ว่าคุณเห็นอะไร ... เพราะฉันไม่เห็นมัน
John Hartsock

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 แบบ multi-kb เพื่อเลือกองค์ประกอบเมื่อ Javascript เสนอฟังก์ชันการทำงานในโค้ดพื้นฐานนั้นเกินความจำเป็นเล็กน้อย
Danejir
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.