我们在javascript中有getElementsByClassName吗?

时间:2009-11-30 09:57:24

标签: javascript

就像在jQuery中我们可以使用$(“。classname”),javascript中也有类似的东西吗?或者如果我们没有这样的方法,那么我该如何实现呢 根据{{​​3}},我将遍历所有标签,然后收集所有与指定类相同的元素。

有没有更好的解决方案?

5 个答案:

答案 0 :(得分:14)

  

我必须迭代所有标签,然后收集所有与指定类相同的元素。

是。但是,有几种方法可以改善您链接的页面的功能:

  • 传入的RegExp-escape类名称,以便它不会被类名中的标点符号破坏。例如,对getElementsByClassName('ab.cd')的调用不应与class="abxcd"匹配。

  • 定义getElementsByClassName的HTML5规范允许多个以空格分隔的类名,所有这些都必须存在于要匹配的元素上。实现这一点。

  • 可选地,允许传入标记名称的提示,以缩小函数必须查看的元素数量,以用于仅影响一种类型标记的常见情况。 (这对于真正的浏览器本地getElementsByClassName调用无效,因此您不应依赖它来过滤掉您不想要的元素。)

示例实施:

if (!('getElementsByClassName' in document)) {
    document.getElementsByClassName= function(classnames, taghint) {
        var exps= classnames.split(/\s+/).map(function(name) {
            name= name.replace(/([/\\^$*+?.()|[\]{}])/g, '\\$1');
            return new RegExp('(^|\\s)'+name+'(\\s|$)');
        });
        var els= this.getElementsByTagName(taghint || '*');
        var matches= [];
        for (var i= 0, n= this.length; i<n; i++)
            var el= els[i];
            if (exps.every(function(exp) {
                return exp.test(el.className);
            }))
                matches.push(el);
        }
        return matches;
    };
}

然而,这也使用了IE还没有的几个ECMAScript第五版(或JavaScript 1.6)数组方法,所以你也必须为这些方法添加回退实现:

if (!('map' in Array.prototype)) {
    Array.prototype.map= function(mapper, that) {
        var other= new Array(this.length);
        for (var i= 0, n= this.length; i<n; i++)
            if (i in this)
                other[i]= mapper.call(that, this[i], i, this);
        return other;
    };
}

if (!('every' in Array.prototype)) {
    Array.prototype.every= function(tester, that) {
        for (var i= 0, n= this.length; i<n; i++)
            if (i in this && !tester.call(that, this[i], i, this))
                return false;
        return true;
    };
}

答案 1 :(得分:5)

不幸的是,浏览器之间不一致。如果您不需要所有jQuery,但仍希望基于CSS选择器进行选择,请查看Sizzle,jQuery使用的选择器库。

答案 2 :(得分:3)

getElementsByClassName

的另一个很好的实现
  

混合XPath和DOM实现;尽可能使用XPath。

if (!('getElementsByClassName' in document)) {
    document.getElementsByClassName = function(className, parentElement) {
        if (Prototype.BrowserFeatures.XPath) {
            var q = ".//*[contains(concat(' ', @class, ' '), ' " + className + " ')]";
            return document._getElementsByXPath(q, parentElement);
        } else {
            var children = ($(parentElement) || document.body).getElementsByTagName('*');
            var elements = [],
                child;
            for (var i = 0, length = children.length; i < length; i++) {
                child = children[i];
                if (Element.hasClassName(child, className)) elements.push(Element.extend(child));
            }
            return elements;
        }
    };
}​

<小时/> P.S:在这里发帖因为我猜它比bobince answer快。没有冒犯:)
来自John Resig的getElementsByClassName Speed Comparison

答案 3 :(得分:2)

某些浏览器,例如Firefox 3支持getElementsByClassName,其他浏览器必须遍历所有标记,因此如果您想支持所有具有单一功能的浏览器,则应使用迭代方法。

最好的解决方案是使用jQuery或任何其他使用最佳可用方法的框架。

答案 4 :(得分:2)

是的,您必须迭代以支持所有浏览器。如果您这样做,请确保您利用浏览器内置的功能:

if(document.getElementsByClassName) {
   return document.getElementsByClassName(className);
} else {
   // iterate
}

除此之外,我和Jochen在一起;使用框架