如何通过类名获取子元素?


131

我正在尝试获取具有class = 4的子跨度。这是一个示例元素:

<div id="test">
 <span class="one"></span>
 <span class="two"></span>
 <span class="three"></span>
 <span class="four"></span>
</div>

我可以使用的工具是JS和YUI2。我可以做这样的事情:

doc = document.getElementById('test');
notes = doc.getElementsByClassName('four');

//or

doc = YAHOO.util.Dom.get('#test');
notes = doc.getElementsByClassName('four');

这些在IE中不起作用。我收到一个错误,指出对象(doc)不支持此方法或属性(getElementsByClassName)。我已经尝试了一些getElementsByClassName跨浏览器实现的示例,但是我无法使它们正常工作,但仍然出现该错误。

我认为我需要的是跨浏览器getElementsByClassName,或者我需要使用doc.getElementsByTagName('span')并循环遍历,直到找到第4类为止。不过我不确定该怎么做。



1
有趣的querySelectorAll是,IE 8+支持更强大的功能,而getElementsByClassNameIE 9+仅支持更强大的功能。如果可以删除IE 7,则可以放心使用querySelectorAll('.4')。顺便说一句,4是一个无效的类名。
Prinzhorn

@paritybit该问题不起作用,因为它仍然使用getElementsByClassName,而较旧版本的IE似乎不支持。编辑:很抱歉它使用标签名称。这可能有效。
spyderman4g63 '08年

@Prinzhorn由于某种原因,我在该产品中没有YUI2选择器实用程序。
spyderman4g63 2012年

@ spyderman4g63我没有谈论任何有关YUI2的问题。document.querySelectorAll是DOM,与YUI无关
Prinzhorn

Answers:


85

使用doc.childNodes通过每个迭代span,然后筛选其一个className等号4

var doc = document.getElementById("test");
var notes = null;
for (var i = 0; i < doc.childNodes.length; i++) {
    if (doc.childNodes[i].className == "4") {
      notes = doc.childNodes[i];
      break;
    }        
}


1
问题是getElementsByClassName在IE8中不起作用。
spyderman4g63 2012年

7
如果element具有多个类,则此代码不起作用。例如:如果您要查找具有“一个”类的元素,而您的元素具有“一二三”类,则此函数将找不到它们。
弗兰·维罗纳

3
@FranVerona出于好奇,简单的“ indexOf('className')> -1”能否解决多类问题?
James Poulose

2
@JamesPoulose,不会。考虑将元素设置为两个类别:较小和较大。thatElement.className将返回一个等于“小而大”的字符串。如果您正在寻找一个名为big的类,则myElement.className.indexOf(“ big”)会产生不等于负1的值,尽管这实际上不是该类的一部分。如果您对类名拥有100%的控制权,那么这样的修复将行得通,只是不能保证,尤其是当您编写要与代码进行交互的代码时,您将无法完全控制。
Deadboy

您应该className像这样使用正则表达式匹配:if(doc.childNode[i].className.match("\s*" + search_class + "\s*")其中变量search_class是您要查找的类名。
WebWanderer

130

使用querySelector和querySelectorAll

var testContainer = document.querySelector('#test');
var fourChildNode = testContainer.querySelector('.four');

IE9及更高版本

;)


感谢您的智能解决方案!
戴金元

1
这将检查所有后代,而不仅仅是孩子。
SUM1

47

接受的答案仅检查直系子女。通常,我们正在寻找具有该类名称的任何后代。

另外,有时我们希望任何包含 className的孩子。

例如:<div class="img square"></div>应该匹配对className“ img”的搜索,即使确切的 className不是“ img”。

这是针对这两个问题的解决方案:

使用该类查找后代元素的第一个实例 className

   function findFirstChildByClass(element, className) {
        var foundElement = null, found;
        function recurse(element, className, found) {
            for (var i = 0; i < element.childNodes.length && !found; i++) {
                var el = element.childNodes[i];
                var classes = el.className != undefined? el.className.split(" ") : [];
                for (var j = 0, jl = classes.length; j < jl; j++) {
                    if (classes[j] == className) {
                        found = true;
                        foundElement = element.childNodes[i];
                        break;
                    }
                }
                if(found)
                    break;
                recurse(element.childNodes[i], className, found);
            }
        }
        recurse(element, className, false);
        return foundElement;
    }

7
不。我希望所有后代,只是希望孩子像问的那样。
保罗·德雷珀

14
仔。您的评论是必要的。很高兴我帮助了13个其他人(像我一样)经常寻找相似的答案,以解决他们的相似但或许更复杂或更普遍的问题。
Augie Gardner'9

5
tnx,我认为此答案更适合用例
Boban Stojanovski

作为记录,我有两个用例,后代使用的频率稍高一些,但是我来这里的是儿童用例。
SUM1

14

使用element.querySelector()。假设:“ myElement”是您已经拥有的父元素。“ sonClassName”是您要查找的孩子的班级。

let child = myElement.querySelector('.sonClassName');

有关更多信息,请访问:https : //developer.mozilla.org/en-US/docs/Web/API/Element/querySelector


由于某种原因,我不得不使用let child = myElement.querySelector('sonClassName');我的案例
Malat

但是您必须在类名querySelector('。sonClassName')旁边添加点,否则它将处理该问题,因为sonClassName是标记名而不是类名
Hamza Dahmoun

10

您可以尝试:

notes = doc.querySelectorAll('.4');

要么

notes = doc.getElementsByTagName('*');
for (var i = 0; i < notes.length; i++) { 
    if (notes[i].getAttribute('class') == '4') {
    }
}

1
我想知道浏览器是否最终不需要使用jQuery之类的功能,很高兴看到它。如果有人好奇,看起来像它支持大多数流行的浏览器:developer.mozilla.org/en-US/docs/Web/API/Document/...
Liron Yahdav

8

在我看来,您似乎想要第四个跨度。如果是这样,您可以这样做:

document.getElementById("test").childNodes[3]

要么

document.getElementById("test").getElementsByTagName("span")[3]

最后一个确保没有任何隐藏的节点可能将其弄乱。


1
谢谢,但是子元素的数量是可变的。
spyderman4g63 '08年

1
在我看来,问题似乎总是要生第四个跨度孩子,因此导致了我的答案。我当然同意,一个函数来获取其他元素中任何索引处的任何类型的元素会更好,但是我没有这样解释问题……再次阅读该问题,我发现我虽然完全被误解了:- )
ChristianJørgensen2013年

TagName而已!很简单。
杰克逊(Jacksonkr)

我经常使用此技术来获取第一个元素,例如document.getElementById(“ test”)。childNodes [0]
Louise Eggleton

@LouiseEggleton还有.firstChild.firstChildElement虽然
YakovL

4

但请注意,旧的浏览器不支持getElementsByClassName

那你就可以

function getElementsByClassName(c,el){
    if(typeof el=='string'){el=document.getElementById(el);}
    if(!el){el=document;}
    if(el.getElementsByClassName){return el.getElementsByClassName(c);}
    var arr=[],
        allEls=el.getElementsByTagName('*');
    for(var i=0;i<allEls.length;i++){
        if(allEls[i].className.split(' ').indexOf(c)>-1){arr.push(allEls[i])}
    }
    return arr;
}
getElementsByClassName('4','test')[0];

似乎可行,但请注意,HTML类

  • 必须以字母开头:AZ或az
  • 后面可以跟字母(A-Za-z),数字(0-9),连字符(“-”)和下划线(“ _”)

3

ID的名称前应加getElementById,没有#符号。然后,您可以span使用来获得子节点getElementsByTagName,并遍历它们以找到具有正确类的子节点:

var doc = document.getElementById('test');

var c = doc.getElementsByTagName('span');

var e = null;
for (var i = 0; i < c.length; i++) {
    if (c[i].className == '4') {
        e = c[i];
        break;
    }
}

if (e != null) {
    alert(e.innerHTML);
}

演示:http//jsfiddle.net/Guffa/xB62U/


抱歉,#是一个错字。我可以选择容器div,但不能通过标签名称选择子元素,因为该功能在ie8中不起作用。
spyderman4g63 2012年

@ spyderman4g63:该getElementsByTagName方法在IE 8中有效。早在IE 5.5中就受支持。developer.mozilla.org/en-US/docs/DOM/...
Guffa

3

我认为,每次可以使用Array及其方法。它们快得多,然后遍历整个DOM /包装器,或将内容推入空数组。此处介绍的大多数解决方案都可以按此处所述(朴素的文章btw)进行调用:

https://medium.com/@chuckdries/traversing-the-dom-with-filter-map-and-arrow-functions-1417d326d2bc

我的解决方案:(在Codepen上进行实时预览:https://codepen.io/Nikolaus91/pen/wEGEYe )

const wrapper = document.getElementById('test') // take a wrapper by ID -> fastest
const itemsArray = Array.from(wrapper.children) // make Array from his children

const pickOne = itemsArray.map(item => { // loop over his children using .map() --> see MDN for more
   if(item.classList.contains('four')) // we place a test where we determine our choice
     item.classList.add('the-chosen-one') // your code here
})


1

这是一个相对简单的递归解决方案。我认为在此进行广度优先搜索是合适的。这将返回与找到的类匹配的第一个元素。

function getDescendantWithClass(element, clName) {
    var children = element.childNodes;
    for (var i = 0; i < children.length; i++) {
        if (children[i].className &&
            children[i].className.split(' ').indexOf(clName) >= 0) {
            return children[i];
         }
     }
     for (var i = 0; i < children.length; i++) {
         var match = getDescendantWithClass(children[i], clName);
         if (match !== null) {
             return match;
         }
     }
     return null;
}

1

您可以通过添加以下行来获取父类。如果您有一个ID,使用会更容易getElementById。尽管如此,

var parentNode = document.getElementsByClassName("progress__container")[0];

然后,您可以querySelectorAll在父级上使用<div>来获取所有div与类匹配的.progress__marker

var progressNodes = progressContainer.querySelectorAll('.progress__marker');

querySelectorAll将获取divprogress__marker


1

现代解决方案

const context = document.getElementById('context');
const selected = context.querySelectorAll(':scope > div');

文件资料


0

2018年6月更新到ES6

    const doc = document.getElementById('test');
    let notes = null;
    for (const value of doc) {
        if (value.className === '4') {
            notes = value;
            break;
        }    
    }

-2

嗯 该示例确实可以在IE8中使用,但在将其应用于对象的情况下可能无效。在我的情况下,将doc设置为一个yui dom对象,然后使用doc.getElementsByClassName。那是它失败的时候。编辑:或者也许我不明白该对象是如何工作的,它只是一个普通的dom对象?
spyderman4g63 '08年

@ spyderman4g63的YUI版本getElementsByClassName是的方法YAHOO.util.Dom。在您的情况下,呼叫看起来像YAHOO.util.Dom.getElementsByClassName('four', 'span', 'test')。您可能应该阅读文档,以更详细地了解该调用在做什么。简短的版本是,它现在将span使用fourDOM元素下面的类来查找test其元素id
汉克·盖伊

@ spyderman4g63是的,get调用的结果只是一个DOM元素。YUI不会像jQuery这样以批发方式“将所有内容包装在特定于框架的对象中”的方式,也不是像Prototype这样的猴子补丁本机对象(不是吗?永远)。在这方面,YUI更像是Dojo。
汉克·盖伊

-3

这是我使用YUI选择器的方法。感谢汉克·盖伊的建议。

notes = YAHOO.util.Dom.getElementsByClassName('four','span','test');

其中四个=类别名称,span =元素类型/标签名称,而test =父ID。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.