jQuery nextUntil() 与评论元素一起工作很奇怪

jQuery nextUntil() works weird with comment element

我需要帮助。我对 jQuery 的 nextUntil() 方法有奇怪的问题。它没有像我期望的那样工作...

我的 HTML 中有两个注释标签,它们分隔了我感兴趣的元素以及我想加入 jQuery 集合的元素。为此,我首先找到两个注释节点,并在第一个节点上应用 nextUntil,将第二个节点作为参数提供。但是第一条评论后面的 nextUntil returns all children 似乎忽略了我传递给它的论点。

我怎样才能防止这种情况发生,并且只得到children两个评论之间的内容?

这是我的代码:

HTML:

<ul>
  <li>1</li>
  <li>2</li>

  <!-- from -->

  <li>3</li>
  <li>4</li>

  <!--  to  -->

  <li>5</li>
  <li>6</li>
</ul>

JavaScript:

  const fromSign = 'from'
  const toSign = 'to'

  // filter callback - return only comment
  // element with specific text
  function commentWith (elm, txt) {
    return elm.nodeType === 8 &&
           elm.nodeValue.trim() === txt
  }

  // Step - 1 find comment with "from"
  // text and save returned element
  const $start = $('ul').contents().filter(
    (idx, elm) => commentWith(elm, fromSign)
  )

  // Find comment with "to"
  // text and save returned element
  const $stop = $('ul').contents().filter(
    (idx, elm) => commentWith(elm, toSign)
  )

  console.info($start, $stop) // So far, so good

  // Step 2 - find all elements
  // between "from" and "to" comments
  let $inner = $start.nextUntil($stop)

  // Not works - inner contains elements
  // beyond "to" comment
  console.log($inner)

  // Step 2 again - find all elements
  // between "from" and "to" comments
  // with "redundant" prev/next
  $inner = $start.nextUntil($stop.prev().next())

  // OK, just li 3 and 4,
  // but why? What am I missing?
  console.log($inner)

PS:如果您使用 <div class="from"><div class="end"> 或其他元素作为 select 的开始和结束,nextAll() 将按预期工作。但是,我想使用注释来标记 selection....

我尝试使用 prev/next "hacks" 作为替代方案(另请参见上面的代码),但是当 [=42= 之前没有元素时它们表现不佳] 在评论标记之后。

您的代码的第一个变体失败的原因是大多数 jQuery 方法只查看 元素 ,而不查看其他节点类型的节点。如 jQuery documentation on contents 中所述:

Please note that most jQuery operations don't support text nodes and comment nodes. The few that do will have an explicit note on their API documentation page.

在您的情况下,对 nextUntil 的调用将仅遍历元素,甚至不会查看其他节点,因此它将 "miss" $stop节点。

解决方法是使用 index()。当开始标记之前没有元素,and/or 停止标记之后没有元素时,这也能很好地工作。如果一个元素节点,则为非元素节点返回的索引将具有的索引。

const fromSign = 'from'
const toSign = 'to'

// filter callback - return only comment
// element with specific text
function commentWith (elm, txt) {
    return elm.nodeType === 8 &&
           elm.nodeValue.trim() === txt
}

// Step - 1 find comment with "from"
// text and save returned index
const startIndex = $('ul').contents().filter(
    (idx, elm) => commentWith(elm, fromSign)
).index();

// Find comment with "to"
// text and save returned index
const stopIndex = $('ul').contents().filter(
    (idx, elm) => commentWith(elm, toSign)
).index();

console.log('indexes:', startIndex, stopIndex);

// Step 2 - get all child elements
// between "from" and "to" comments
let $inner = $('ul').children().slice(startIndex, stopIndex);

// Now it works - inner contains the elements between the markings
console.log('selected first and last text:', $inner.first().text(), $inner.last().text());
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
    <li>1</li>
    <li>2</li>

    <!-- from -->

    <li>3</li>
    <li>4</li>

    <!--  to  -->

    <li>5</li>
    <li>6</li>
</ul>