QuerySelectorAll 和 getElementsBy * 方法返回什么?

getElementsByClassName(以及类似于 getElementsByTagNamequerySelectorAll的函数)的工作原理是否与 getElementById相同,或者它们返回的是一个元素数组?

我问这个问题的原因是因为我正在尝试使用 getElementsByClassName改变所有元素的样式。

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


//works
document.getElementById('myIdElement').style.size = '100px';
99894 次浏览

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

然而,这些方法 getElementsByClassName, getElementsByName, getElementsByTagName和 < a href = “ https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementsByTagNameNS”rel = “ noReferrer”> getElementsByTagNameNS 返回一个可迭代的元素集合。

方法名提供了提示: getElement意味着 独一无二,而 getElements意味着 不止一个

方法 querySelector也返回一个元素,而 querySelectorAll返回一个可迭代的集合。

可迭代集合可以是 NodeListHTMLCollection

指定 getElementsByNamequerySelectorAll返回 NodeList; 指定另一个 getElementsBy*方法返回 HTMLCollection,但请注意,有些浏览器版本的实现方式不同。

这两种集合类型都没有提供 Element、 Nodes 或类似类型所提供的相同属性; 这就是为什么从 document.getElements读取 style... (... )失败的原因。 换句话说: NodeList或者 HTMLCollection没有 style,只有 Elementstyle
这些“类似数组”的集合是包含零个或多个元素的列表,为了访问这些元素,需要对其进行迭代。 虽然您可以像迭代数组一样对它们进行迭代,但请注意,它们是来自 Arrays不同

在现代浏览器中,您可以使用 Array.from将这些可迭代文件转换为适当的 Array; 然后您可以使用 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";
}

旁白: .childNodes产生 活下去 NodeList.children产生 活下去 HTMLCollection,所以这两个读取器也需要小心处理。


有一些类似 JQuery的库可以使 DOM 查询更短一些,并在“一个元素”和“一组元素”之上创建一个抽象层:

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

对于任何支持 ES5 + 的浏览器(基本上在 IE8之上的任何浏览器) ,您都可以使用 Array.prototype.forEach方法。

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

一个 href = “ https://caniuse.com/mdn-javascript _ builtins _ array _ foreach”rel = “ nofollow norefrer”> caniuse source

以下描述摘自 这一页:

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>)集合:

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

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

您正在使用数组作为对象,这是 getElementbyIdgetElementsByClassName是:
  • 如果没有找到带 ID 的元素,则 getElementbyId将返回 元素对象或 null
  • 如果没有找到匹配的元素,getElementsByClassName将返回一个 实时 HTMLCollection,长度可能为0

GetElementsByClassName

getElementsByClassName(classNames)方法接受一个字符串,该字符串 包含一组无序的唯一空格分隔标记 当调用时,该方法必须返回一个实时的 对象,该对象包含文档中的所有元素 具有该参数中指定的所有类,并且已经获取了 如果没有标记,则通过在空格上拆分字符串来实现 参数中指定,则该方法必须返回一个空的 节点列表

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

GetElementById

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属性。

它返回类似 Array 的列表。

你可以用 Array 作为例子

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

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

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


Array.from(boxes).forEach(v => v.style.background = 'green');
console.log(Array.from(boxes));
.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>

正如您可以在代码片段中看到的,在使用 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>

您可以通过运行

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

但是对于第一个元素,它将使用 class. myElement。

如果您希望对类中的所有元素都应用这种方法,我建议您使用

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

换句话说

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

  • document.querySelectorAll()使用指定的选择器选择 < strong > all 元素,并在数组中返回它们。类似于 document.getElementsByClassName(),只适用于类和 document.getElementsByTagName()标记。


为什么使用 querySelector?

它仅仅是为了方便和简洁的目的而使用的。


为什么要使用 getElement/sBy? *

更快的表现。


为什么会有这样的性能差异?

两种选择方式的目的都是创建一个 节点列表以供进一步使用。 QuerySelectors使用选择器生成一个静态 NodeList,因此必须首先从头开始创建它。 < br > GetElement/sBy * 立即适应当前 DOM 的现有活动 NodeList。

因此,什么时候使用哪种方法取决于你/你的项目/你的设备。


信息

< p > 所有方法的演示 < br > NodeList 文档 < br > 性能测试

/*
* 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

答案是 为了 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>

超级老派的解决方案:

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

因此,我被告知,这是从我的问题,我应该删除我的,我会这样做,我可以保持论坛干净,并保持提问的权利。

因为我认为我的和这个问题真的不同,我会指出我的答案,所以我会完成这一页的知识和信息不会丢失。

提问

  1. < p > 我在代码片段中有一段代码是 document.getElementsByClassName("close")[0],那么 [0]在做什么呢?

  2. 我从未见过 getElementsByClassName中使用方括号的用途是什么?

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

回答我

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

  2. < p > 同样的事情。

  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">&times;</span>
<p>Some text in the Modal..</p>
</div>
</div>

更新

似乎我真的不能删除我的问题和人们不满意,我真的不知道我该怎么办。