在 DOM 遍历的时候,我们经常遇到这样的场景:不想只拿紧挨着的一个兄弟(用 next()),也不想一口气把所有兄弟都抱走(用 nextAll()),而是想精准地取出一段范围——从当前位置开始,一直到某个特定的兄弟为止。这种“点到为止”的需求,用 nextUntil() 方法来实现就再合适不过了。
这个方法的核心逻辑是:沿着 DOM 树向前遍历,把从起始元素之后、到指定停止元素之前的所有兄弟元素都找出来。 它就像在一排队伍中,你指定了“从张三后面开始,到李四前面结束”,中间那几个人就是你要的结果。
核心语法
$(selector).nextUntil(stop, filter)
两个参数都可以省略,功能上会有明显区别:
-
stop:可选。它告诉方法“到哪里该停下了”。可以是一个选择器字符串、一个 jQuery 对象、或者一个 DOM 元素。重点是,停止元素本身不包含在返回结果里。 -
filter:可选。一个选择器表达式,对上一步拿到的范围进行二次筛选,只留下符合条件的元素。
假如你连 stop 参数都不传,或者传入的选择器根本匹配不到任何东西,那么 nextUntil() 的行为就等价于 nextAll(),会一股脑把后面所有兄弟都返回给你。我个人认为,这种设计虽然灵活,但也容易因为参数笔误导致意料之外的大批量选中,实际编码时得稍微留点心。
本节课程知识要点
-
nextUntil()返回的是一个范围,不含起点元素,也不含stop指定的那个终点元素。 -
它只向前找后面的兄弟,不会反向查找。
-
如果终点找不到,行为退化为
nextAll(),这是一个需要注意的细节。 -
结合
filter参数,可以在划定好的范围内做进一步的精准过滤,非常实用。
一、基础用法:指定一个停下来地方
我们先从最直观的例子开始。假设一个容器里,从 <h1> 标题开始,后面混排了各种元素,直到某个 <h3> 标题出现。我们想把 <h1> 之后、<h3> 之前的这一段元素全都加上样式,不包括 <h3> 本身。
HTML 结构如下:
<div id="box">
<h1>一级标题</h1>
<h2>二级标题</h2>
<ul>
<li>列表项</li>
</ul>
<span>行内文本</span>
<p>这是一段描述文字</p>
<h3>三级标题,在这里停下</h3>
</div>
<button>选中范围内的兄弟</button>
jQuery 代码非常简洁:
$("button").click(function(){
$("h1").nextUntil("h3").css({
"color": "blue",
"border": "2px solid blue"
});
});
代码运行起来后点击按钮,<h2>、<ul>、<span>、<p> 这四个元素会染上蓝色边框和文字。紧跟在它们后面的 <h3> 虽然是停止标记,但它自己不会被选中。我早期没用过这个方法之前,会专门写循环去判断 $(this).is("h3") 然后 return false 来跳出,逻辑绕且可读性差。接触 nextUntil() 之后,这类问题一行代码就交代清楚了。
二、进阶筛选:在范围里只挑出想要的
在项目中,光划定范围还不够。一个区域里可能混杂着各种标签,我们可能只对其中某一种标签感兴趣。这时候 filter 参数就派上用场了。
来看这个场景:在 <h1> 和 <h3> 之间,散落着 <p> 和好几个 <span>,我们偏偏只希望高亮其中的 <span> 元素。
<div id="wrap">
<h1>文章主标题</h1>
<p>第一段说明文字</p>
<span>标签一</span>
<h4>一个小标题</h4>
<span>标签二</span>
<h3>章节结束标题</h3>
<span>这个标签在后面,不会扰</span>
</div>
<button>只高亮范围里的 span</button>
对应的 jQuery 逻辑:
$("button").click(function(){
$("h1").nextUntil("h3", "span").css({
"color": "darkred",
"border": "2px dashed red"
});
});
这次点击按钮,只有“标签一”和“标签二”会变化。<h3> 后面的那个 <span> 根本不在划定范围内,自然不受影响。同时,划定范围内的 <p> 和 <h4> 也因为不满足 filter 条件而被直接忽略。
为什么不用 nextAll("span") 然后再手动判断位置?因为那样会把 <h3> 后面的 span 也拉进来,后续过滤逻辑就复杂了。nextUntil() 加上 filter,从源头就把范围锁死,后续操作干干净净。
三、精细过滤:利用 ID 或类名锁定单个元素
filter 参数的灵活之处在于,它不仅支持标签选择器,同样可以用 ID、类名等任意合法的 jQuery 选择器。这样就能在整片范围里只对某一个特定元素做操作。
看下面这个例子,<h1> 到 <h3> 之间有三个 <span>,各自带有不同的 ID。我们只想让其中 id="s2" 的那个发生变化。
<div id="content">
<h1>标题</h1>
<span id="s1">代码段1</span>
<span id="s2">代码段2(目标)</span>
<span id="s3">代码段3</span>
<h3>停止点</h3>
</div>
<button>精准操作代码段2</button>
jQuery 代码:
$("button").click(function(){
$("h1").nextUntil("h3", "#s2").css({
"color": "green",
"border": "2px solid green"
});
});
这个场景在开发中的映射很常见。比如说一个 DOM 结构由后端模板循环生成,你不能随意改动 HTML 结构,但又需要在前端对某个区域内的特定元素做动态高亮或修改。这时候,靠 nextUntil() 划定安全边界,再用 ID 选择器精确落地,两个参数相互配合,既精准又不会意外污染其他区域的同名元素。
从个人经验出发,nextUntil() 和 prevUntil() 可以看作一对镜像工具。当你熟悉了向前找兄弟的 nextUntil(),回头再用 prevUntil() 去向后查找,思维模型是一致的。掌握其中一个,另一个也就水到渠成了。