正如标题所说,我试图找出 jQuery 的 .prevAll()
和 .nextAll()
背后的逻辑(并在纯 JS 中复制)。查看源代码并没有像我希望的那样有帮助。
重要的是要记住 prevNodes 也可以嵌套在其他元素中。所以这不是选择 sibling 的问题。
这是我到目前为止的想法:
// args should be two selectors, source node and previous nodes
const prevAll = (...args) => {
// select all the nodes that matches the two selectors
let elements = document.querySelectorAll(args.join(', '));
elements = Array.from(elements);
// get index of the source node inside all elements
const index = elements.indexOf(document.querySelector(args[0]));
// return everything before that index
if (index >= 0)
return elements.slice(0, index);
return [];
}
const prevNodes = prevAll('.start-node', '.prev-node')
测试
// args should be two selectors, source node and previous nodes
const prevAll = (...args) => {
// select all the nodes that matches the two selectors
let elements = document.querySelectorAll(args.join(', '));
elements = Array.from(elements);
// get index of the source node inside all elements
const index = elements.indexOf(document.querySelector(args[0]));
// return everything before that index
if (index >= 0)
return elements.slice(0, index);
return [];
}
const prevNodes = prevAll('.start-node', '.prev-node')
console.log(prevNodes)
<div class="prev-node"></div>
<div class="prev-node"></div>
<div class="prev-node"></div>
<div class="wrapper">
<div class="prev-node"></div> <!-- this will be included as well -->
</div>
<!-- start here -->
<div class="start-node"></div>
<div class="next-node"></div>
由于很多原因,这显然不是完美的解决方案。我认为起始节点选择器应该是一个唯一的节点。否则这将无法按预期工作。我可以将第一个参数作为真正的 Element 对象传递,但这样逻辑会复杂得多。
关于如何处理这个问题还有其他想法吗?
最佳答案
这只是 prevAll()
但应该很明显如何走另一条路 (.nextElementSibling
) :)
let prevAll = (selector, restrictionSelector = "") => {
let elements = Array.from(document.querySelectorAll(selector)),
restrictedElements = restrictionSelector ? Array.from(document.querySelectorAll(restrictionSelector)) : [],
result = [];
elements.forEach((element) => {
let prevElement = element.previousElementSibling;
while (prevElement) {
if (restrictedElements.length === 0 || restrictedElements.some((r) => r === prevElement)) {
result.push(prevElement);
}
prevElement = prevElement.previousElementSibling;
}
});
return result;
}
let test = prevAll("div.start-node");
console.log(test);
test = prevAll("div.start-node", "div.wrapper");
console.log(test);
<div class="prev-node"></div>
<div class="prev-node"></div>
<div class="prev-node"></div>
<div class="wrapper">
<div class="prev-node"></div>
</div>
<!-- start here -->
<div class="start-node"></div>
<div class="next-node"></div>
关于jquery - $.prevAll([selector]) 和 $.nextAll([selector]) 如何工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38661696/