通过ID获取多个元素

81
我有一个页面,正文中有像这样的锚链接标签:
<a id="test" name="Name 1"></a>
<a id="test" name="Name 2"></a>
<a id="test" name="Name 3"></a>

这个ID一直都是一样的,但名字会不同。

我需要将这些锚点标签的名字填充到列表中,例如:Name 1,Name 2,Name 3。目前为止,我已经做到了这一步:

document.write(document.getElementById("readme").name);

这行代码输出第一个锚点标签的名称。我需要一种通过ID获取多个元素的方法。


非常感谢任何帮助。


53
ID 必须是唯一的,HTML 规范要求如此,不能相同。 - Quentin
5
请参考,该页面不是有效的HTML,因此当处理该页面时,用户代理的行为是未定义的。 根据W3c规范id属性“必须在文档内唯一”。 这就是唯一标识符的整个意义,这也是为什么您不能使用DOM方法获取具有相同ID的多个元素(因为后者没有任何意义)。 - Andrzej Doyle
1
可能是 JavaScript 和 getElementById 的重复。 - Andy E
2
你是指 getElementById("test").name 吗? - Ken Sharp
2
@Quentin 在完美的世界里是这样,但你会感到惊讶。 - Robert Sinclair
15个回答

107
如果您可以更改标记,则可能希望使用 class
HTML
<a class="test" name="Name 1"></a>
<a class="test" name="Name 2"></a>
<a class="test" name="Name 3"></a>

JS

var elements = document.getElementsByClassName("test");
var names = '';
for(var i = 0; i < elements.length; i++) {
    names += elements[i].name;
}
document.write(names);

jsfiddle演示


如果我使用<p>或<div>而不是<a>,上面的fiddle就无法工作。 - Pratik bhatt
如果您想要一个适用于所有三个元素 <p>、<div>、<a> 的属性,那么可以使用像 title 这样的全局属性。因此,它将是 <p title="my attribute">。然后可以这样读取值:elements[i].title。您可以在同一个 jsfiddle 中尝试此操作。https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes - erickb
1
这个回答如何解决获取元素ID的问题? - one-hand-octopus

51
今天你可以通过以下方式选择具有相同id属性的元素:
document.querySelectorAll('[id=test]');

或者使用jQuery:

$('[id=test]');

CSS选择器#test { ... }也应该适用于所有具有id = "test"的元素。 但唯一的问题是:document.querySelectorAll('#test')(或$('#test'))- 只会返回具有此id的第一个元素。这好还是不好 - 我无法判断。但有时很难遵循唯一id标准
例如,您有评论小部件,其中包含HTML-ID和JS代码,可以使用这些HTML-ID工作。 迟早,您将需要多次呈现此小部件,以在单个页面中对不同对象进行评论:并且在这里,标准将被打破(通常没有时间或不允许-重写内置代码)。

6
正确回答问题且比使用$('*').filter方法更有效。尽管除非你知道自己在做什么,否则使用类(class)是最好的解决方案。 - Berty
1
感谢您按照问题要求进行回答,而不是挑战它。使用类是一个很好的解决方案...除非你正在处理其他人的代码/网页。对于像Tampermonkey脚本这样的东西,我们没有让页面“正确”的奢侈。我想隐藏Quora所有新的付费“订阅”帖子,它们都有id="content_paywall_card_title_text",并且与常规帖子没有其他明显区别的重要特征。因此,这个实际上回答了问题的答案非常有帮助。谢谢。 - Dewi Morgan

24

与其他人所说的不同,使用相同的Id属性命名多个元素不会阻止页面加载,但是当尝试通过Id选择元素时,只会返回具有指定id的第一个元素。更何况,使用相同的id甚至不是有效的HTML。

因此,请勿使用重复的id属性。如果您认为需要这样做,则应该考虑使用class。例如:

<div id="div1" class="mydiv">Content here</div>
<div id="div2" class="mydiv">Content here</div>
<div id="div3" class="mydiv">Content here</div>

注意每个元素都有一个不同的id,但是相同的class。与您上面所做的相反,这是合法的HTML语法。您为“ .mydiv”(点表示类)使用的任何CSS样式都将正确地作用于具有相同类的每个单独元素。

借助Snipplr的帮助,您可以使用此方法通过指定特定类名来获取每个元素:

function getAllByClass(classname, node) {

    if (!document.getElementsByClassName) {
        if (!node) {
            node =  document.body;
        }

        var a = [],
            re = new RegExp('\\b' + classname + '\\b'),
            els = node.getElementsByTagName("*");

        for (var i = 0, j = els.length; i < j; i++) {
            if (re.test(els[i].className)) {
                a.push(els[i]);
            }
        }
    } else {
        return document.getElementsByClassName(classname);
    }

    return a;
}

以上脚本将返回一个数组,请确保你适当地进行调整。


4
@Shaz,你是个真正使用纯JavaScript的人,因此你保持了真实性。+1。 - Loktar
1
@Loktar,所以重新发明轮子突然变得可取了吗?有数十个生产质量的库可以将上述代码简化为一行代码。 - Sean Patrick Floyd
10
首先,OP并没有要求使用jQuery,为什么要增加页面加载时间、稍微降低速度,如果用户只需要某些功能呢?当然,使用jQuery编写的代码可能会更短,但总体上要大得多。我不会每次想吃牛排就买整头牛。 - Loktar
2
@Loktar 我认为,如果你要做任何非平凡的事情,拥有一个JavaScript DOM操作库是必不可少的。只需从CDN获取它,它会被缓存。除此之外,上面的函数还存在一些浏览器漏洞。 - Raynos
@Loktar,楼主显然不太了解,所以这并不重要,相反,指向一个库可能会使事情变得更好。 - Sean Patrick Floyd
3
@Sean Patrick Floyd 我同意这一点,我的主要观点是对于10行代码,你不应该只是依赖于使用框架。 - Loktar

14

这是我想到的一个函数

function getElementsById(elementID){
    var elementCollection = new Array();
    var allElements = document.getElementsByTagName("*");
    for(i = 0; i < allElements.length; i++){
        if(allElements[i].id == elementID)
            elementCollection.push(allElements[i]);

    }
    return elementCollection;
}

显然,有一种约定受到了Prototype和可能其他主要JavaScript库的支持。

然而,我发现dollar sign函数已成为近乎默认的快捷方式,用于调用document.getElementById()。让我们面对它,我们都经常使用document.getElementById()。不仅需要输入时间,还会增加代码的字节数。

这是来自prototype的函数:

function $(element) {
  if (arguments.length > 1) {
    for (var i = 0, elements = [], length = arguments.length; i < length; i++)
      elements.push($(arguments[i]));
    return elements;
  }
  if (Object.isString(element))
    element = document.getElementById(element);
  return Element.extend(element);
}

[来源]


13

你应该使用querySelectorAll,它会将每个匹配的结果写入一个数组中,并且可以通过forEach来获取单个元素。

document.querySelectorAll('[id=test]').forEach(element=> 
    document.write(element);
});

13

您不能有重复的ID。ID应该是唯一的。您可能需要使用一个专门的类。


1
是的,你可以有重复的ID。这不是一个好主意,但你可以这样做。 - Ethan Furman

2
如果您不太关心HTML的有效性,那么在多个元素上具有相同ID可能是有用的。一个例子是测试。通常我们通过找到具有特定类的所有元素来识别要进行测试的元素。然而,如果我们仅出于测试目的添加类,则我认为这是错误的。类是用于样式而非识别的。
如果ID用于识别,为什么只能有一个元素具有特定标识符呢?特别是在今天的前端世界中,具有可重用组件,如果我们不想使用类进行识别,则需要使用ID。但是,如果我们使用多个组件,则会有多个具有相同ID的元素。
我认为这是可以接受的。如果这对您来说是禁忌,那很好,我理解您的观点。让我们同意不同意并继续前进。
如果您想要实际查找所有相同名称的ID的解决方案,那么它就是:
function getElementsById(id) {
    const elementsWithId = []
    const allElements = document.getElementsByTagName('*')
    for(let key in allElements) {
        if(allElements.hasOwnProperty(key)) {
            const element = allElements[key]
            if(element.id === id) {
                elementsWithId.push(element)
            }        
        }
    }
    return elementsWithId
}

编辑,ES6胜利:

function getElementsById(id) {
    return [...document.getElementsByTagName('*')].filter(element => element.id === id)
}

类是用于样式而不是标识的。虽然这可能是最初的意图,但现在情况并非如此。请考虑来自MDN的以下句子:“类允许CSS和Javascript选择和访问特定元素”,以及“鼓励Web开发人员使用描述元素语义目的的名称,而不是元素呈现”的名称。 - James Thorpe
我认为这是一个权宜之计,因为意识到ID过于有限。现在类具有两个目的,这不是一件好事。我们可能需要另一个属性(也许是“分类法”?)仅用于标识,但适用于可能存在多个元素。尽管如此,在缺乏这种属性的情况下,我可以接受一些无效的HTML。 - sypl

2

不允许有多个相同ID的元素,getElementById返回其ID为elementId的元素。如果不存在这样的元素,则返回null。如果有多个元素具有此ID,则行为未定义。


1
使用querySelectorAll,您可以使用css选择器选择要选择的元素,而无需相同的id:
var elems = document.querySelectorAll("#id1, #id1, #id3");

1

没有重复的id,这是基础。如果你有一个html结构如下:

<a id="test1" name="Name_1">a1</a>
<a id="test2" name="Name_2">a2</a>
<a id="test3" name="Name_3">a3</a>

现今,使用ES6的map()方法,您可以选择具有不同id的多个元素:
const elements = ['test1', 'test2', 'test3'].map(id => document.getElementById(id));

console.log(elements);
// (3) [a#test1, a#test2, a#test3] 

当然,如果它们有相同的class,那么选择它们会更容易。
具有不同id的元素在一个数组中。
例如,您可以使用forEach()方法从DOM中删除它们。
elements.forEach(el => el.remove());

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