在JavaScript中按类A或B获取元素

时间:2014-02-18 12:32:19

标签: javascript getelementsbyclassname

是否可以获取具有一个指定类的元素?这与获取指定类的 all 的元素相同。

例如,我想捕获其类列表包含onetwothree的所有元素。

也许是这样的:

var oneTwoThree = document.getElementsByClassName("one, two, three");

我也不想使用jQuery。是getElementsByClassName每个类的唯一选项并将它们组合起来吗?

2 个答案:

答案 0 :(得分:12)

querySelector几乎接受任何CSS选择器:

var oneTwoThree = document.querySelectorAll('.one, .two, .three');

答案 1 :(得分:4)

  

我也不想使用jQuery。是每个类的getElementsByClassName的唯一选项并将它们组合起来吗?

通过使用querySelectorAll(已回答),它将搜索并为您进行组合。 IE9 + {IE8(仅限CSS2选择器)

否则,getElementsByClassName不是唯一可用的方法,甚至在某些旧版浏览器(IE9 +,FF3 +)上也无法使用。

但是,您可以使用的任何其他方法都需要您将结果组合在一起。所以,就像演示一样,我为你创建了几个例子。

根据white spaces

定义HTML4.01 class attribute
  

“此属性为一个元素分配一个类名或一组类名。可以为任意数量的元素分配相同的类名。多个类名必须用空格字符分隔。”

var whiteSpaces = '[\u0009\u000A\u000B\u000C\u000D\u0020\u00A0\u1680\u180E\u2000\u2001\u2002\u2003\‌​u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028\u2029\uFEFF]';

根据space characters

定义HTML5 3.2.5.7 The class attribute
  

每个HTML元素都可以指定一个类属性。

     

如果指定了属性,则该属性的值必须是一组以空格分隔的标记,表示该元素所属的各种类。

     

HTML元素分配给它的类包含在类空间上拆分class属性的值时返回的所有类。 (忽略重复。)

     

为元素分配类会影响CSS中选择器中的类匹配,DOM中的getElementsByClassName()方法以及其他此类功能。

     

作者可以在class属性中使用令牌没有其他限制,但鼓励作者使用描述内容性质的值,而不是描述内容所需表示的值。

     

DOM规范中定义的className和classList IDL属性反映了类内容属性。 [DOM]“

var whiteSpaces = '[ \n\r\t\f]';

定义开始结束echaratcers

var starts = '(^|' + whiteSpaces + ')',
    ends = '(' + whiteSpaces +'|$)';

跨浏览器(DOM walker)

function walkTheDOM(node, func) {
    func(node);
    node = node.firstChild;
    while (node) {
        walkTheDOM(node, func);
        node = node.nextSibling;
    }
}

function getElementsByClassName1(node, className) {
    var regex = new RegExp(starts + className + ends),
        results = [];

    walkTheDOM(node, function (currentNode) {
        if (regex.test(currentNode.className)) {
            results.push(currentNode);
        }
    });

    return results;
}

跨浏览器(getElementsByClassName)

function getElementsByClassName2(node, className) {
    var array = [],
        regex = new RegExp(starts + className + ends),
        elements = node.getElementsByTagName("*"),
        length = elements.length,
        i = 0,
        element;

    while (i < length) {
        element = elements[i];
        if (regex.test(element.className)) {
            array.push(element);
        }

        i += 1;
    }

    return array;
}

现代浏览器(IE9 +)

function getElementsByClassName3(node, className) {
    var results = [],
        treeWalker = document.createTreeWalker(
        node,
        NodeFilter.SHOW_ELEMENT, {
            acceptNode: function (thisNode) {
                var accept = NodeFilter.FILTER_SKIP;

                if (thisNode.classList.contains(className)) {
                    accept = NodeFilter.FILTER_ACCEPT;
                }

                return accept;
            }
        }, false);

    while (treeWalker.nextNode()) {
        results.push(treeWalker.currentNode);
    }

    return results;
}

现代浏览器(IE9 +)

function getElementsByClassName4(node, className) {
    return Array.prototype.slice.call(document.getElementsByClassName(className));
}

跨浏览器Array.indexOf

function indexOf(array, searchElement, fromIndex) {
    var length = array.length,
        val = -1,
        index;

    if (length !== 0) {
        if (arguments.length > 2) {
            fromIndex = fromIndex >> 0;
        } else {
            fromIndex = 0;
        }

        if (fromIndex < length) {
            if (fromIndex < 0) {
                fromIndex = length - Math.abs(fromIndex);
            }

            if (fromIndex < 0) {
                fromIndex = 0;
            }

            for (index = fromIndex; index < length; index += 1) {
                if (index in array && searchElement === array[index]) {
                    val = index;
                    break;
                }
            }
        }
    }

    return val;
}

跨浏览器Array.filter

function filter(array, fn, thisArg) {
    var length = array.length,
        arr = [],
        index,
        element;

    for (index = 0; index < length; index += 1) {
        if (index in array) {
            element = array[index];
            if (fn.call(thisArg, element, index, array)) {
                arr.push(element);
            }
        }
    }

    return arr;
};

合并结果并维持秩序

function getElements(node, classes, func) {
    if (typeof classes === 'string') {
        classes = classes.split(/\s*,\s*/);
    }

    var length = classes.length,
        results = [],
        index,
        name;

    for (index = 0; index < length; index += 1) {
        name = classes[index];
        if (name.charAt(0) === '.') {
            name = name.slice(1);
        }

        results = results.concat(func(node, name));
    }

    return filter(results.reverse(), function (element, index, arr) {
        return index <= indexOf(arr, element);
    }).reverse();
}

<强>测试

<div class='A'></div>
<div class='B'></div>
<div class='A B'></div>
<div class='C'></div>

console.log(getElements(document, '.A, .B', getElementsByClassName1));
console.log(getElements(document, '.A, .B', getElementsByClassName2));
console.log(getElements(document, '.A, .B', getElementsByClassName3));
console.log(getElements(document, '.A, .B', getElementsByClassName4));
console.log(document.querySelectorAll('.A, .B'));

jsFiddle

最后在jsPerf

上进行性能比较