querySelectorAll() 和 getElementsBy*() 方法返回什么?

2024-11-02 20:59:00
admin
原创
37
摘要:问题描述:getElementsByClassName(以及类似的函数如getElementsByTagName和) 的工作原理是否querySelectorAll相同getElementById或者它们是否返回一个元素数组?我之所以问这个问题是因为我想使用 来改变所有元素的样式getElementsByCl...

问题描述:

getElementsByClassName(以及类似的函数如getElementsByTagName和) 的工作原理是否querySelectorAll相同getElementById或者它们是否返回一个元素数组?

我之所以问这个问题是因为我想使用 来改变所有元素的样式getElementsByClassName。见下文。

//doesn't work
document.getElementsByClassName('myElement').style.size = '100px';

//works
document.getElementById('myIdElement').style.size = '100px';

解决方案 1:

您的getElementById代码可以工作,因为 ID 必须是唯一的,因此函数总是返回一个元素(或者null如果没有找到任何元素)。

但是,方法
getElementsByClassName、、

返回可getElementsByName迭代

元素集合。getElementsByTagName`getElementsByTagNameNS`

方法名称提供了提示:getElement暗示单数,而getElements暗示复数

该方法querySelector还返回单个元素,并querySelectorAll返回可迭代集合。

可迭代集合可以是NodeListHTMLCollection

getElementsByNamequerySelectorAll都指定返回NodeList;其他getElementsBy*方法指定返回HTMLCollection,但请注意,某些浏览器版本对此的实现不同。

这两种集合类型都不具备元素、节点或类似类型所提供的属性;这就是读取… … 失败的原因styledocument.getElements换句话说()aNodeList或 anHTMLCollection没有style;只有 anElementstyle


这些“类似数组”的集合是包含零个或多个元素的列表,您需要迭代这些元素才能访问它们。虽然您可以像迭代数组一样迭代它们,但请注意它们与s不同Array

在现代浏览器中,你可以用将这些可迭代对象转换为适当的数组Array.from;然后可以使用forEach和其他数组方法,例如迭代方法:

Array.from(document.getElementsByClassName("myElement"))
  .forEach((element) => element.style.size = "100px");

在不支持Array.from迭代方法的旧浏览器中,你仍然可以使用Array.prototype.slice.call。然后你可以像迭代真实数组一样对其进行迭代:

var elements = Array.prototype.slice
    .call(document.getElementsByClassName("myElement"));

for(var i = 0; i < elements.length; ++i){
  elements[i].style.size = "100px";
}

您还可以迭代NodeListHTMLCollection本身,但请注意,在大多数情况下,这些集合是实时的(MDN 文档、DOM 规范),即它们会随着 DOM 的变化而更新。因此,如果您在循环时插入或删除元素,请确保不要意外跳过某些元素或创建无限循环。MDN 文档应始终注明方法返回的是实时集合还是静态集合。

例如,在现代浏览器中NodeList提供了一些迭代方法forEach

document.querySelectorAll(".myElement")
  .forEach((element) => element.style.size = "100px");

for也可以使用一个简单的循环:

var elements = document.getElementsByClassName("myElement");

for(var i = 0; i < elements.length; ++i){
  elements[i].style.size = "100px";
}

另外:.childNodesyields a live NodeList.childrenYields a live HTMLCollection,因此这两个 getter 也需要小心处理。


有一些像jQuery这样的库可以使 DOM 查询变得更短一些,并在“一个元素”和“元素集合”上创建一个抽象层:

$(".myElement").css("size", "100px");

解决方案 2:

您正在使用数组作为对象,getElementbyId
之间的区别getElementsByClassName在于:

  • getElementbyId如果未找到具有 ID 的元素,则将返回Element 对象或 null

  • getElementsByClassName如果未找到匹配的元素,将返回一个活动的 HTMLCollection ,其长度可能为 0

通过类名获取元素

getElementsByClassName(classNames)方法采用一个字符串,该字符串包含一组无序的、以空格分隔的、表示类的唯一标记。调用该方法时,必须返回一个活动
NodeList对象,该对象包含文档中所有具有该参数中指定的所有类的元素,这些类是通过在空格上拆分字符串获得的。如果参数中未指定任何标记,则该方法必须返回一个空的 NodeList。

https://www.w3.org/TR/2008/WD-html5-20080610/dom.html#getelementsbyclassname

获取元素的 ID

getElementById() 方法访问具有指定 id 的第一个元素。

https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementById

在您的代码中:

1- document.getElementsByClassName('myElement')。style.size ='100px';

不会按预期工作,因为getElementByClassName将返回一个数组,并且该数组将具有style属性,您可以element通过迭代它们来访问每个数组。

这就是该函数getElementById对你起作用的原因,该函数将返回直接对象。因此你将能够访问该style属性。

解决方案 3:

ES6提供了Array.from()方法,它从类数组或可迭代对象创建一个新的数组实例。

let boxes = document.getElementsByClassName('box');

setTimeout(() => {
  Array.from(boxes).forEach(v => v.style.background = 'green');
  console.log(Array.from(boxes));
}, 500);
.box {
  width: 50px;
  height: 50px;
  margin: 5px;
  background: blue;
  display: inline-block;
}
<div class='box'></div>
<div class='box'></div>
<div class='box'></div>
<div class='box'></div>

运行代码片段Hide results展开片段

正如您在代码片段中看到的,使用Array.from()函数后,您就可以操作每个元素。

使用jQuery的相同解决方案。

$('.box').css({'background':'green'});
.box {
  width: 50px;
  height: 50px;
  margin: 5px;
  background: blue;
  display: inline-block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class='box'></div>
<div class='box'></div>
<div class='box'></div>
<div class='box'></div>

运行代码片段Hide results展开片段

解决方案 4:

以下描述取自此页面:

getElementsByClassName() 方法以 NodeList 对象的形式返回文档中具有指定类名的所有元素的集合。

NodeList 对象表示节点的集合。可以通过索引号访问节点。索引从 0 开始。

提示:您可以使用 NodeList 对象的 length 属性来确定具有指定类名的元素的数量,然后循环遍历所有元素并提取所需的信息。

因此,作为参数getElementsByClassName会接受一个类名。

如果这是你的 HTML 主体:

<div id="first" class="menuItem"></div>
<div id="second" class="menuItem"></div>
<div id="third" class="menuItem"></div>
<div id="footer"></div>

然后var menuItems = document.getElementsByClassName('menuItem')将返回上部 3 个的集合(不是数组)<div>,因为它们与给定的类名匹配。

然后,您可以使用以下命令迭代此节点(<div>在本例中为 s )集合:

for (var menuItemIndex = 0 ; menuItemIndex < menuItems.length ; menuItemIndex ++) {
   var currentMenuItem = menuItems[menuItemIndex];
   // do stuff with currentMenuItem as a node.
}

有关元素和节点之间的差异的更多信息,请参阅这篇文章。

解决方案 5:

换句话说

  • document.querySelector()仅选择指定选择器的第一个元素。因此它不会输出数组,而是一个单一值。与document.getElementById()仅获取 ID 元素类似,因为 ID 必须是唯一的。

  • document.querySelectorAll()使用指定的选择器选择所有元素并将它们返回到数组中。与document.getElementsByClassName()类和document.getElementsByTagName()标签类似。

为什么要使用 querySelector?

它仅仅是为了方便和简洁。

为什么要使用 getElement/sBy?*

更快的性能。

为什么会有这种性能差异?

两种选择方式的目的都是创建一个NodeList以供进一步使用。querySelectors
使用选择器生成一个静态 NodeList,因此必须先从头开始创建。getElement

/sBy*会立即适应当前 DOM 的现有活动 NodeList。

因此,何时使用哪种方法取决于您/您的项目/您的设备。

信息

所有方法的演示

NodeList 文档

性能测试

解决方案 6:

您可以通过运行获取单个元素

document.querySelector('.myElement').style.size = '100px';

但它将适用于类为 .myElement 的第一个元素。

如果你想将它应用于所有具有该类的元素,我建议你使用

document.querySelectorAll('.myElement').forEach(function(element) {
    element.style.size = '100px';
});

解决方案 7:

它返回类似数组的列表。

例如,将其设为一个数组

var el = getElementsByClassName("elem");
el = Array.prototype.slice.call(el); //this line
el[0].appendChild(otherElem);  

解决方案 8:

/*
 * To hide all elements with the same class, 
 * use looping to reach each element with that class. 
 * In this case, looping is done recursively
 */

const hideAll = (className, i=0) => {
if(!document.getElementsByClassName(className)[i]){ //exits the loop when element of that id does not exist
  return; 
}

document.getElementsByClassName(className)[i].style.visibility = 'hidden'; //hide element
return hideAll(className, i+1) //loop for the next element
}

hideAll('appBanner') //the function call requires the class name

解决方案 9:

任何支持 ES5+ 的浏览器(基本上是 IE8 以上的浏览器)都可以使用该Array.prototype.forEach方法。

Array.prototype.forEach.call(document.getElementsByClassName('answer'), function(el) {
    el.style.color= 'red';
});

运行代码片段Hide results展开片段

卡尼尤斯源

解决方案 10:

因此我被告知这与我的问题重复,我应该删除我的问题,我会这样做,这样我就可以保持论坛清洁并保留提出问题的权利。

因为我认为我的问题和这个问题确实不同,所以我会指出我的答案,所以我将完成此页面中的知识并且信息不会丢失。

问题

  1. 我的代码片段中有document.getElementsByClassName("close")[0],它起什么作用[0]

  2. 我从未见过方括号的用途,getElementsByClassName它有何用途?

  3. 另外,我如何将其转换为 jQuery?

回答

  1. 代码片段中有一个[0]它实际上被用作一个数组,并且因为它是 0,所以它指的是第一次使用指定的类。

  2. 同上。

  3. 我真的做不到,也没有人回答。在代码中引用的部分,event. target我不能用$("#myModal")代替document.getElementById("myModal"),我认为它们应该是等效的,但在这种情况下,用 jQuery 形式替代标准形式不会产生预期的效果。

    window.onclick = function(event) {
      if (event.target == modal) {
        modal.style.display = "none";
      }
    }
var modal = document.getElementById("myModal");
var btn = document.getElementById("myBtn");
var span = document.getElementsByClassName("close")[0];

btn.onclick = function() {
  modal.style.display = "block";
}
span.onclick = function() {
  modal.style.display = "none";
}
window.onclick = function(event) {
  if (event.target == modal) {
    modal.style.display = "none";
  }
}
body {font-family: Arial, Helvetica, sans-serif;}

.modal {
  display: none;
  position: fixed;
  z-index: 1;
  padding-top: 100px;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  overflow: auto;
  background-color: rgb(0,0,0);
  background-color: rgba(0,0,0,0.4);
}

.modal-content {
  background-color: #fefefe;
  margin: auto;
  padding: 20px;
  border: 1px solid #888;
  width: 80%;
}

.close {
  color: #aaaaaa;
  float: right;
  font-size: 28px;
  font-weight: bold;
}

.close:hover,
.close:focus {
  color: #000;
  text-decoration: none;
  cursor: pointer;
}
<h2>Modal </h2>

<button id="myBtn">Open Modal</button>

<div id="myModal" class="modal">
  <div class="modal-content">
    <span class="close">×</span>
    <p>Some text in the Modal..</p>
  </div>
</div>

运行代码片段Hide results展开片段

更新

看来我真的无法删除我的问题,而且人们对此不满意,我真的不知道我该怎么办。

解决方案 11:

超级老派的解决方案:

        [].forEach.call(document.getElementsByClassName('myClass'), function (el) {
            el.style.size = '100px';
        });

解决方案 12:

针对 Drenzii 具体案例的回答......

您可以创建一个适用于任何word元素的函数并传入您想要转换的元素的编号,例如:

// Binds `wordButtons` to an (array-like) HTMLCollection of buttons
const wordButtons = document.getElementsByClassName("word");

// Applies the `slantWord` function to the first word button
slantWord(1);

// Defines the `slantWord` function
function slantWord(wordNumber) {
  const index = wordNumber - 1; // Collection index is zero-based
  wordButtons[index].style.transform = "rotate(7deg)"; // Transforms the specified button
}
<div class="wordGameContainer">
  <button class="word word1">WORD 1</button>
  <button class="word word2">WORD 2</button>
  <button class="word word3">WORD 3</button>
  <button class="word word4">WORD 4</button>
</div>

<div>
  <button onclick="moveWord()" class="playButton">PLAY</button>
</div>

运行代码片段Hide results展开片段

相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   601  
  华为IPD与传统研发模式的8大差异在快速变化的商业环境中,产品研发模式的选择直接决定了企业的市场响应速度和竞争力。华为作为全球领先的通信技术解决方案供应商,其成功在很大程度上得益于对产品研发模式的持续创新。华为引入并深度定制的集成产品开发(IPD)体系,相较于传统的研发模式,展现出了显著的差异和优势。本文将详细探讨华为...
IPD流程是谁发明的   7  
  如何通过IPD流程缩短产品上市时间?在快速变化的市场环境中,产品上市时间成为企业竞争力的关键因素之一。集成产品开发(IPD, Integrated Product Development)作为一种先进的产品研发管理方法,通过其结构化的流程设计和跨部门协作机制,显著缩短了产品上市时间,提高了市场响应速度。本文将深入探讨如...
华为IPD流程   9  
  在项目管理领域,IPD(Integrated Product Development,集成产品开发)流程图是连接创意、设计与市场成功的桥梁。它不仅是一个视觉工具,更是一种战略思维方式的体现,帮助团队高效协同,确保产品按时、按质、按量推向市场。尽管IPD流程图可能初看之下显得错综复杂,但只需掌握几个关键点,你便能轻松驾驭...
IPD开发流程管理   8  
  在项目管理领域,集成产品开发(IPD)流程被视为提升产品上市速度、增强团队协作与创新能力的重要工具。然而,尽管IPD流程拥有诸多优势,其实施过程中仍可能遭遇多种挑战,导致项目失败。本文旨在深入探讨八个常见的IPD流程失败原因,并提出相应的解决方法,以帮助项目管理者规避风险,确保项目成功。缺乏明确的项目目标与战略对齐IP...
IPD流程图   8  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用