正如标题所说,我试图找出jQuery的.prevAll()
和.nextAll()
背后的逻辑(并在简单的JS中复制)。查看源代码并没有像我希望的那样有用。
重要的是要记住,prevNodes也可以嵌套在其他元素中。所以这不是选择兄弟姐妹的问题。
这是我到目前为止所提出的:
// 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>
&#13;
由于很多原因,这显然不是完美的解决方案。我相信起始节点选择器应该是一个唯一的节点。否则这不会按预期工作。我可以将第一个参数作为真正的Element对象传递,但逻辑会更复杂。
关于如何处理此事的任何其他想法?
答案 0 :(得分:1)
这只是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>
答案 1 :(得分:0)
我在纯JS中可以想到的复制prevAll函数的唯一方法是通过选择器找到当前元素,选择该元素的第一个父元素并循环遍历子元素,只拉动具有相同元素的子节点节点名称作为您选择的元素。
示例(这是非常粗略的,不需要多个参数,如果你有一个包含多个结果的选择器,你也会遇到麻烦):
function prevAll(selector) {
elements = document.querySelector(selector);
var nodeType = elements.nodeName;
var totalElements = elements.parentElement.childNodes;
var re = [];
for(i = 0; i < totalElements.length; i++) {
if(totalElements[i].nodeName != nodeType) {
continue;
}
if(totalElements[i] == elements) {
break;
} else {
re[re.length] = totalElements[i];
}
}
return re;
}
最大的问题是jQuery可以处理元素的数组返回并且可以成功地将方法应用于该数组,JS主要是属性,并且在调整元素时不支持元素数组。
答案 2 :(得分:0)
我最近对使用没有jQuery的prevAll和nextAll有相同的要求。 这是我的方法:
function prevAll(element, result) {
if(element.previousElementSibling){
result.push(element.previousElementSibling);
element=element.previousElementSibling;
prevAll(element, result);
}
return result;
}
function nextAll(element, result) {
if(element.nextElementSibling{
result.push(element.nextElementSibling);
element=element.nextElementSibling;
nextAll(element,result);
}
return result;
}
通话:
var element=document.querySelector('.class-name');//element has to be any dom element
Array.prototype.forEach.call(prevAll(element, []), function (el) {
//Do what you need to do with the previous elements here
});
Array.prototype.forEach.call(nextAll(element, []), function (el) {
//Do what you need to do with the next elements here
});
答案 3 :(得分:0)
这就是我在最近的项目中所做的:
const nextAll = (element) => {
let siblingElements = []
let elem = document.querySelector(element)
while (elem.nextElementSibling) {
siblingElements.push(elem.nextElementSibling)
elem = elem.nextElementSibling
}
return siblingElements
}
致电:
nextAll('.layer')