我试图通过以下方式获取具有特定类的第一个元素,该类跟随用纯 JS(无 JQuery)单击的元素,但 get el.nextSibling 不是函数错误。最初我使用的是 JQueryparents().next() 但想用纯 JS 来做到这一点:
const togglers = document.querySelectorAll('.toggler');
//console.log(togglers);
togglers.forEach(function(el) {
el.addEventListener('click', function(e) {
//const content = el.innerHTML;
//console.log(content);
el.nextSibling('.folder-content').style.display = 'block';
})
});
<div class="folder">
<div class="toggler">Click me 1</div>
<div class="folder-content" style="display: none">
Lorem ipsum
</div>
</div>
<div class="folder">
<div class="toggler">Click me 2</div>
<div class="folder-content" style="display: none">
Lorem ipsum
</div>
</div>
如有任何帮助,我们将不胜感激:)
nextElement
是一个属性,而不是函数,因此您不要将 ()
与它一起使用。也就是说,使用 nextSibling
会给你带来你不想要的空白内容。相反,您可以使用 nextElementSibling
:
el.nextElementSibling.style.display = 'block';
const togglers = document.querySelectorAll('.toggler');
//console.log(togglers);
togglers.forEach(function(el) {
el.addEventListener('click', function(e) {
//const content = el.innerHTML;
//console.log(content);
el.nextElementSibling.style.display = 'block';
})
});
<div class="folder">
<div class="toggler">Click me 1</div>
<div class="folder-content" style="display: none">
Lorem ipsum
</div>
</div>
<div class="folder">
<div class="toggler">Click me 2</div>
<div class="folder-content" style="display: none">
Lorem ipsum
</div>
</div>
您可以添加一个
while
循环来搜索第一个符合您条件的 nextSibling
。
编辑: 正如@j08691指出的,如果你的真实代码只关心元素而不关心其他节点类型,你可以使用nextElementSibling。
const togglers = document.querySelectorAll('.toggler');
//console.log(togglers);
togglers.forEach(function(el) {
el.addEventListener('click', function(e) {
var nextSibling = el.nextSibling;
while (nextSibling) {
if (
nextSibling.nodeType == Node.ELEMENT_NODE
&& nextSibling.classList.contains('folder-content')
) {
nextSibling.style.display = 'block';
break;
}
nextSibling = nextSibling.nextSibling;
}
})
});
<div class="folder">
<div class="toggler">Click me 1</div>
<div>not this</div>
<div>not this</div>
<div class="folder-content" style="display: none">
Lorem ipsum 1!
</div>
<div>not this</div>
<div class="toggler">Click me 1.5</div>
<div>not this</div>
<div class="folder-content" style="display: none">
Lorem ipsum 1.5!
</div>
<div>not this</div>
<div>not this</div>
</div>
<div class="folder">
<div class="toggler">Click me 2</div>
<div class="folder-content" style="display: none">
Lorem ipsum
</div>
</div>
<div class="folder">
<div class="toggler">Click me 3</div>
<div>no folder content here!</div>
</div>
我正在构建这个答案,而其他人进来了,为了多样性和简洁的 DOM 编程,这是另一种给这只猫换皮的方法:
这是您提供的初始代码,调用一个单独的函数来执行所请求的操作(查找与指定查询字符串匹配的下一个同级)
const togglers = document.querySelectorAll('.toggler');
togglers.forEach(function(el, i) {
el.addEventListener('click', function(e) {
searchNextSiblings(el, ".folder-content", function(ele) {
ele.style.display = "block";
});
})
});
您会注意到我提供的函数称为
searchNextSiblings
,它需要三个参数:
这是函数本身:
function searchNextSiblings(ele, q, fn) {
let flag = false;
const nodeIterator = document.createNodeIterator(
ele.parentNode,
NodeFilter.SHOW_ELEMENT,
function(node) {
if (ele.isSameNode(node)) flag = true;
if (!flag) return NodeFilter.FILTER_REJECT;
else {
if (node.matches(q)) {
flag = false;
return NodeFilter.FILTER_ACCEPT
};
}
});
let currentNode;
while (currentNode = nodeIterator.nextNode()) {
fn(currentNode);
}
}
这是带注释的版本:
function searchNextSiblings(ele, q, fn) {
// we want to search from the first Element provided
// to properly search we will set our crawler to begin
// from its parent node, and when we reach the first Element
// we will begin searching for the Query String
// in order to do this we declare a flag to False
// when we reach the first Element we will set it as True
// This will let us know when we can search for the Matching Query
let flag = false;
const nodeIterator = document.createNodeIterator(
ele.parentNode, //root to search from
NodeFilter.SHOW_ELEMENT, //set the iterator to search for elements
function(node) {
if (ele.isSameNode(node)) flag = true;
//if we've found the first Element, set the flag to True
if (!flag) return NodeFilter.FILTER_REJECT;
//if the flag is False, continue searching for first Element
else {
//if we have found the first Element,
//we are now searching for the Element that Matches the Query
if (node.matches(q)) {
//if we find a matching element
flag = false;
//set the flag to false to stop the search
return NodeFilter.FILTER_ACCEPT
//return the found node
};
}
});
// the above declares the node iterator
// but does not start it up
let currentNode;
while (currentNode = nodeIterator.nextNode()) {
fn(currentNode);
}
//the above "starts up" the nodeIterator
}
const togglers = document.querySelectorAll('.toggler');
togglers.forEach(function(el, i) {
el.addEventListener('click', function(e) {
searchNextSiblings(el, ".folder-content", function(ele) {
ele.style.display = "block";
});
})
});
function searchNextSiblings(ele, q, fn) {
let flag = false;
const nodeIterator = document.createNodeIterator(
ele.parentNode,
NodeFilter.SHOW_ELEMENT,
function(node) {
if (ele.isSameNode(node)) flag = true;
if (!flag) return NodeFilter.FILTER_REJECT;
else {
if (node.matches(q)) {
flag = false;
return NodeFilter.FILTER_ACCEPT
};
}
});
let currentNode;
while (currentNode = nodeIterator.nextNode()) {
fn(currentNode);
}
}
<div class="folder">
<div class="toggler">Click me 1</div>
<div class="folder-content" style="display: none">
Lorem ipsum
</div>
</div>
<div class="folder">
<div class="toggler">Click me 2</div>
<div class="folder-content" style="display: none">
Lorem ipsum
</div>
</div>
节点与元素 在 HTML DOM 术语中:
节点是所有节点(元素节点、文本节点、注释节点)。
元素之间的空白也是文本节点。
元素只是元素节点。
兄弟姐妹 vs 元素兄弟姐妹 兄弟姐妹是“兄弟”和“姐妹”。
兄弟节点是具有相同父节点的节点(在相同的子节点列表中)。
元素同级是具有相同父级的元素(在相同的子级列表中)。
子节点与子节点 childNodes 返回子节点(元素节点、文本节点和注释节点)。
children 返回子元素(不是文本和注释节点)。
nextSibling 与 nextElementSibling nextSibling 返回下一个节点(元素节点、文本节点或注释节点)。元素之间的空白也是文本节点。
nextElementSibling 返回下一个元素(不是文本和注释节点)。
previousSibling 与 previousElementSibling previousSibling 返回前一个节点(元素节点、文本节点或注释节点)。元素之间的空白也是文本节点。
previousElementSibling 返回前一个元素(不是文本和注释节点)。