从头开始重新实现 getElementsByClassName(仅限 Vanilla JS)
Reimplementing getElementsByClassName from scratch (Vanilla JS only)
本着更加熟悉 DOM 和递归的精神,我决定从头开始重新创建 getElementsByClassName(仅限 vanilla JS,没有 jQuery)。目前,我可以在 DOM 中找到所有具有我想要的 class 的元素,但我无法想出一种方法来仅获取具有两个特定 [=27= 的元素]es(或更多)。
<div class="one two">
<h1 class="one">
<span class="one two">
</h1>
</div>
我当前的实现 returns 如我所料,返回包含 class 'one' 的每个元素:
getElementsByClassName('one');
[<div class="one two"></div>, <h1 class="one"></h1>, <span class="one two"</span>]
我想达到的目标:
getElementsByClassName('one two');
[<div class="one two"></div>, <span class="one two"</span>]
我 运行 遇到的一个问题是 classList.contains:
element.classList;
// ['one, 'two'];
element.classList.contain("one");
//returns true since the value actually exists
//PROBLEM:
element.classList.contains("one two");
//this is looking for "one two" in the array and not 'one' and 'two'.
//this returns false & my code breaks
//How would I be able to do something like this, even if it
//means recreating my own helper contains function?
contains('one','two');
我的函数:
var getElementsByClassName = function(className){
var results = [];
function getClass(nodeList){
var childList = nodeList.children;
_forEach(childList, function(node) {
//1st level body check
if(node.classList && node.classList.contains(className)){
results.push(node);
}
//has children, recurse
if(node.children) {
getClass(node);
}
else {
getClass(node);
}
});
}
getClass(document.body);
return results;
}
//Helper forEach function to iterate over array like DOM objects
var _forEach = function(collection, func) {
for(var i = 0; i < collection.length; i++) {
func(collection[i], i, collection);
}
}
代码中的注释——我没有为您实现它,只是指出您要做什么:
var getElementsByClassName = function(className){
// ***Here, split className on whitespace into an array **
var results = [];
function getClass(nodeList){
var childList = nodeList.children;
_forEach(childList, function(node) {
//1st level body check
// **Here, only include the element if Array#every is true,
// **where you give Array#every a function that does your
// classList.contains on the name for that iteration
if(node.classList && node.classList.contains(className)){
results.push(node);
}
//has children, recurse
if(node.children) {
getClass(node);
}
else {
getClass(node);
}
});
}
getClass(document.body);
return results;
}
本着更加熟悉 DOM 和递归的精神,我决定从头开始重新创建 getElementsByClassName(仅限 vanilla JS,没有 jQuery)。目前,我可以在 DOM 中找到所有具有我想要的 class 的元素,但我无法想出一种方法来仅获取具有两个特定 [=27= 的元素]es(或更多)。
<div class="one two">
<h1 class="one">
<span class="one two">
</h1>
</div>
我当前的实现 returns 如我所料,返回包含 class 'one' 的每个元素:
getElementsByClassName('one');
[<div class="one two"></div>, <h1 class="one"></h1>, <span class="one two"</span>]
我想达到的目标:
getElementsByClassName('one two');
[<div class="one two"></div>, <span class="one two"</span>]
我 运行 遇到的一个问题是 classList.contains:
element.classList;
// ['one, 'two'];
element.classList.contain("one");
//returns true since the value actually exists
//PROBLEM:
element.classList.contains("one two");
//this is looking for "one two" in the array and not 'one' and 'two'.
//this returns false & my code breaks
//How would I be able to do something like this, even if it
//means recreating my own helper contains function?
contains('one','two');
我的函数:
var getElementsByClassName = function(className){
var results = [];
function getClass(nodeList){
var childList = nodeList.children;
_forEach(childList, function(node) {
//1st level body check
if(node.classList && node.classList.contains(className)){
results.push(node);
}
//has children, recurse
if(node.children) {
getClass(node);
}
else {
getClass(node);
}
});
}
getClass(document.body);
return results;
}
//Helper forEach function to iterate over array like DOM objects
var _forEach = function(collection, func) {
for(var i = 0; i < collection.length; i++) {
func(collection[i], i, collection);
}
}
代码中的注释——我没有为您实现它,只是指出您要做什么:
var getElementsByClassName = function(className){
// ***Here, split className on whitespace into an array **
var results = [];
function getClass(nodeList){
var childList = nodeList.children;
_forEach(childList, function(node) {
//1st level body check
// **Here, only include the element if Array#every is true,
// **where you give Array#every a function that does your
// classList.contains on the name for that iteration
if(node.classList && node.classList.contains(className)){
results.push(node);
}
//has children, recurse
if(node.children) {
getClass(node);
}
else {
getClass(node);
}
});
}
getClass(document.body);
return results;
}