我可以使用getElementsByTagName选择多个标签吗?

时间:2014-01-17 18:42:01

标签: javascript html getelementsbytagname

我正在使用javascript代码段,以便我网站的访问者使用以下javascript增加所有段落的字体大小:

function increaseFontSize() {  

    var paragraphs = document.getElementsByTagName('p'); 

    for(i=0;i<paragraphs.length;i++) {   

        if(paragraphs[i].style.fontSize) { 
            var s = parseInt(paragraphs[i].style.fontSize.replace("px",""));
        } else {   
            var s = 14;
        }

        if(s != max) {  
            s += 1; 
        } 
        paragraphs[i].style.fontSize = s+"px"
    } 
} 

如何在此代码中加入“li”,以便“p”和“li”是受影响的选定元素?

我还想避免在我的“li”或“ul”中添加一个类或一个id。有没有办法一次选择两个标签?

5 个答案:

答案 0 :(得分:71)

不,您只需拨打一次getElementsByTagName即可选择多个代码。您可以使用getElementsByTagName进行两次查询,也可以使用querySelectorAll

JSFiddle

var elems = document.querySelectorAll('p,li')

答案 1 :(得分:2)

Q

我可以使用getElementsByTagName选择多个标签吗?

A

是的,但您必须多次使用getElementsByTagName。

虽然您的示例仅指定Document.getElementsByTagName()我假设您希望这也适用于element.getElementsByTagName()。

getElementsByTagName返回一个HTMLCollection对象,因此理想的结果是返回所有标记名称的HTMLCollection元素对象的方法。

有关HTMLCollection's

的注意事项
  • 他们无法修改。
  • 它们是DOM节点的live列表
  • 只有三种方法可以直接自己创建getElementsByTagNamegetElementsByClassNamegetElementsByTagNameNS
  • 您可以创建一个可能具有HTMLCollection类型属性的对象,例如nodeList.children

由于HTMLCollection's无法修改,我们可以做的最好的事情是尽可能多地返回一个类似于HTMLCollection's的对象,请参阅Create a HTMLCollection或创建nodeList并返回children属性。

首先,我们需要收集 HTMLCollection 的所有匹配元素

最简单的方法是使用返回nodeList的{​​{3}}函数。

var nodeList = document.querySelectorAll(selector);

另一种方法是对每个标记使用getElementsByTagName方法,将返回的HTMLCollection对象转换为数组,以便将它们合并在一起。

喜欢这样。

var HTMLCollectionArray = [];
var names = selector.split(",");
for (var i = 0, n = names.length; i < n; i++){
    HTMLCollectionArray = HTMLCollectionArray.concat(Array.prototype.slice.call(document.getElementsByTagName(names[i]))); 
}

也可以使用相同的方法将nodeList转换为数组。

HTMLCollectionArray = Array.prototype.slice.call(nodeList);

我们现在可以将所有元素作为数组返回,或者尝试返回HTMLCollection。

如果我们要返回HTMLCollection,则必须将元素移动或复制到单个parentNode,以便我们可以访问parentNode.children

我发现使用document.createDocumentFragment效果最佳。

var createDocumentFragment = document.createDocumentFragment();
for (var i = 0; i < HTMLCollectionArray.length; i++) {
    createDocumentFragment.appendChild(HTMLCollectionArray[i]);
};
HTMLCollection = createDocumentFragment.children; 
return HTMLCollection;

虽然这会返回正确的类型(HTMLCollection),但在调用方法时它不会返回元素的实际状态。 DOM已经过修改以实现这一目标。不是个好主意。

所以这让我们做了假的HTMLCollection

window.MyNodeList = function(elements) {

    for ( var i = 0; i < elements.length; i += 1 ) {
        this[i] = elements[i];
    }
    Object.defineProperty( this, 'length', {
        get: function () {
            return elements.length;
        }
    });
    Object.freeze( this );
};

window.MyNodeList.prototype.item  function ( i ) {
    return this[i] != null ? this[i] : null;
}

window.MyHTMLCollection =  function(elements) {
  MyNodeList.call(this, elements);
}

MyHTMLCollection.prototype = Object.create(MyNodeList.prototype);

MyHTMLCollection.prototype.constructor = MyHTMLCollection;

window.MyHTMLCollection.prototype.namedItem =  function ( name ) {
    for ( var i = 0; i < this.length; i += 1 ) {
        if ( this[i].id === name || this[i].name === name ) {
            return this[i];
        }
    }
    return null;
}

用法

var HTMLCollection = new MyHTMLCollection(elementsArray);

现在把它们拼凑起来。

我还实现了'getElementsByClassNames'方法以及'getElementsByTagNames',它们都使用相同的核心方法getElementsBySelector

Element.prototype.getElementsByTagNames = Document.prototype.getElementsByTagNames = function(selector){
    return this.getElementsBySelector(selector, 'getElementsByTagName');
}
Element.prototype.getElementsByClassNames = Document.prototype.getElementsByClassNames = function(selector){
    return this.getElementsBySelector(selector, 'getElementsByClassName');
}

我们只希望querySelectorAllDocument接口继承我们的新方法,因为它们调用所有Element接口中不存在的原型方法。例如getElementsByClassNamequerySelectorAll

如果您想缩小代码,那么您可以使用Node.prototype而不是声明Element.prototype.Document.prototype.

Node.prototype.getElementsByTagNames = function(selector){
    return this.getElementsBySelector(selector, 'getElementsByTagName');
}
Node.prototype.getElementsByClassNames = function(selector){
    return this.getElementsBySelector(selector, 'getElementsByClassName');
}

请确保您不要在任何非NodeDocument的节点上使用它。

Element.prototype.getElementsBySelector = Document.prototype.getElementsBySelector = function (selector, HTMLCollectionType) {

    var HTMLCollectionArray = [];

    if(typeof this.querySelectorAll !== 'undefined'){

        var nodeList = this.querySelectorAll(selector);
        HTMLCollectionArray = Array.prototype.slice.call(nodeList);

    } else {

        if(typeof HTMLCollectionType !=='undefined' && typeof this[HTMLCollectionType] !== 'undefined'){

            var names = selector.split(",");
            for (var i = 0, n = names.length; i < n; i++){
                HTMLCollectionArray = HTMLCollectionArray.concat(Array.prototype.slice.call(this[HTMLCollectionType](names[i]))); 
            }
        }
    }

    return new MyHTMLCollection(HTMLCollectionArray);

    /* 
    var createDocumentFragment = document.createDocumentFragment();
    for (var i = 0; i < HTMLCollectionArray.length; i++) {
        createDocumentFragment.appendChild(HTMLCollectionArray[i]);
    };
    HTMLCollection = createDocumentFragment.children;
    return HTMLCollection;
    */
}

用法

var element = document.getElementById('id');
element.getElementsbyClassNames('class1,class2,class2'); 
element.getElementsbyTagNames('li,div,p'); 

document.getElementsbyClassNames('class1,class2,class2'); 
document.getElementsbyTagNames('li,div,p'); 

答案 2 :(得分:1)

迟了一年,但如果您打算在项目中多次使用所需的功能,并且您无法访问querySelector(),则可能需要使用Node扩展/** * @param {Array} tags - The array of tagNames to search for. * @return {Array} - The elements with matching tagNames. */ Node.prototype.getElementsByTagNames = function (tags) { var elements = []; for (var i = 0, n = tags.length; i < n; i++) { // Concatenate the array created from a HTMLCollection object elements = elements.concat(Array.prototype.slice.call(this.getElementsByTagName(tags[i]))); } return elements; }; 对象。 简单功能:

<强>的JavaScript

getElementsByTagName()

Working demo on JSFiddle.

所有这一切都是迭代一组标记名称,然后在每次迭代时使用getElementById()获取相应的元素。

当然,这可以在任何元素上使用,就像你在任何Node对象上使用类似函数一样 - 例如document - 你不是仅限{{1}}。

答案 3 :(得分:-1)

一次选择两个标签?是的,我们可以一次创建一个循环。
这是您的整个示例。但是P和LI都有一个循环(一个数组):

function increaseFontSize() {  

    Array.from(document.getElementsByTagName('p'))
        .concat(Array.from(document.getElementsByTagName('li'))).forEach(el => {


            if(el.style.fontSize) { 
                var s = parseInt(el.style.fontSize.replace("px",""));
            } else {   
                var s = 14;
            }

            if(s != max) {  
                s += 1; 
            } 
            el.style.fontSize = s+"px"
    });
} 

说明:
Array.from()
这是从集合中制作真实数组的官方方法。
某些浏览器可能在HTMLCollection上支持forEach,但在规范中不支持。
即使这样,他们也可能不支持concat()方法。
使用from()将创建集合的浅表副本。
这是HTMLCollection的优势,因为可以在迭代过程中修改项目 对Array内部元素的修改仍然是对原始对象的修改。

现在我们有两个标准数组,可以使用concat()将它们连接起来,并使用forEach迭代连接的结果。

答案 4 :(得分:-1)

这仅适用于 Chrome,并不能作为解决方案,但发现它是出色的 javascript 行为:

before and after different

它甚至适用于您可能只想同时选择包含多种类型标签的元素的 html 集合。可以这样做,例如:

document.getElementsByTagName('p' || 'li') //-> selects both P and LI elements.