jquery - $.prevAll([selector]) 和 $.nextAll([selector]) 如何工作?

标签 jquery algorithm jquery-selectors

正如标题所说,我试图找出 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/

相关文章:

javascript - 使用 flask, jinja2 将 html 复选框值存储到列表中

c# - 如何评估 C# 中的自定义括号表达式?

algorithm - 基于分数对用户进行排名的数据结构的建议

jquery - 如何 jQuery 选择只有一个复选框的 <td>

javascript - jQuery 输入[名称 =""] 选择器不起作用

jquery - 在 mvc3 中单击 View 按钮时弹出窗口?

jquery - 下拉菜单溢出问题: Mouseenter and Mouseleave + slideDown and slideUp

jquery 选择器第二个选择器不工作

javascript - API 不会接受串联输入

java - Long[]数组和long[]数组的区别?