0

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

我的 HTML 中有两个注释标签,它们分隔了我感兴趣的元素以及我想要进入 jQuery 集合的元素。为此,我首先找到两个评论节点,并应用nextUntil第一个,提供第二个作为参数。但nextUntil返回所有跟随第一条评论的孩子,似乎忽略了我传递给它的论点。

我怎样才能防止这种情况发生,并且只得到两条评论之间的孩子?

这是我的代码:

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">and<div class="end">或其他元素来选择开始和结束,nextAll()则按预期工作。但是,我想使用注释来标记选择......

我尝试使用prev/ next“hacks”作为替代方案(另请参见上面的代码),但是当注释标记之前和/或之后没有元素时,它们的表现不佳。

4

1 回答 1

0

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

请注意,大多数 jQuery 操作不支持文本节点和注释节点。少数这样做的人会在他们的 API 文档页面上有明确的说明。

在您的情况下,调用nextUntil将仅遍历元素,甚至不查看其他节点,因此它将“错过” $stop节点。

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

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>

于 2017-05-18T18:42:19.280 回答