通过类和ID获取元素 - JavaScript

208

好的,我之前尝试过JavaScript,但写的最有用的东西是一个CSS样式切换器。所以我在这方面还比较新手。假设我有以下HTML代码:

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

我该如何将Hello world!更改为Goodbye world!

我知道如何使用document.getElementsByClassNamedocument.getElementById,但我想更加具体化。如果这个问题以前已经被问过,那么很抱歉。

8个回答

355

首先,您需要使用类似于 getElementById 的函数选择元素。

var targetDiv = document.getElementById("foo").getElementsByClassName("bar")[0];
getElementById只返回一个节点,但是getElementsByClassName返回一个节点列表。由于只有一个带有该类名的元素(据我所知),您可以只获取第一个元素(这就是[0]的作用-它就像一个数组)。然后,您可以使用.textContent更改HTML内容。
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
13
@rvighne OP的确切要求是他“希望更具体”。提问者询问如何在DOM树遍历中变得更具体。使用getElementByClassName并不引起混淆,但我可以理解为什么有人会认为我指出了两者都是必需的。它们不是必需的。如果您想仅针对属于特定ID下的某个节点而非另一个节点下相同类别的元素,请使用此方法。 - Joseph Marikle
1
最好编辑这个答案,将 .innerHtml 更改为 .textContent,以增强复制/粘贴编码者的安全性。 - codescribblr
那么在2022年,几乎每个“.”上都加入一些可选链怎么样? - danh

21

你可以这样做:

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

9
我们也可以利用CSS选择器与querySelector一起使用。
var targetDiv = document.querySelector('#foo .bar');
targetDiv.textContent = "Goodbye world!";

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
是的,我的意思是支持你的答案,但同时也指出可以在shim中使用qSA,以便在IE8中仍然可以使用本地代码。尽管仔细看了你的解决方案,你还有一些需要修复的问题。 - user113716
var i = 0, var child = fooDiv.childNodes[i] 是无效的。 i <= fooDiv.childNodes 没有实际意义。 childNode.className.test("bar") 没有 childNode 变量,字符串也没有 test() 方法。 - user113716
@Ӫ_._Ӫ 你是正确的,i<=fooDiv.childNodes应该是i<=fooDiv.childNodes.length,而我的test()函数有问题,但是...var i = 0, var child = fooDiv.childnodes[i]是完全有效的。 - John Hartsock
显示剩余5条评论

6
最简单的方法是:
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}]`);
}

1
如果 OP 询问的是 ID,他们可以在 idOfChild 上使用 getElementById,因为 ID 必须对文档唯一。但是 OP 询问了一个 ID 中的类。如果您已经使用 querySelector,那么只需使用适当的选择器即可更容易地实现:document.querySelector('#id .class') - Heretic Monkey

4
你可以在DOM元素上使用getElementByIdgetElementsByClassName,而不仅仅是document

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


尽管这段代码可能回答了问题,但提供关于它如何解决问题以及为什么能够解决问题的额外背景信息将会增强答案的长期价值。 - Jean-Francois Gagnon

3

递归函数:

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

以上示例中存在一个小错误。在else路径中,您必须首先检查是否找到了某些内容,而不是立即返回。否则,其他子节点将无法循环遍历。类似这样: if(elementToReturn) { return elementToReturn; } - Jannik

-8

你不应该使用 document.getElementByID,因为它只适用于具有固定ID的客户端控件。相反,你应该像下面的示例一样使用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

如果您想要删除或编辑任何操作,只需在后面添加“.”并执行相应的操作即可。

19
使用热核武器来杀死一只鹿是可行的,但有点过度杀伐。当JavaScript在其基础代码中提供了该功能时,使用多KB的jQuery库来选择一个元素稍微有些过度杀伐。 - Danejir
只有在使用像ASP.NET WebForms或其他创建ID以原始用户输入ID结尾的服务器端框架时,此答案才有意义。我所知道的任何框架都不会修改CSS类,因此没有理由在“class”上使用属性选择器。 - Heretic Monkey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接