尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

jQuery选择器详解:从基础语法到动态页面实战

发布时间:2026/9/26 8:42:59

资讯中心
01
ARTICLE

jQuery选择器详解:从基础语法到动态页面实战

jQuery选择器详解:从基础语法到动态页面实战
1. 开始之前jQuery选择器的定位与学习路径1.1 为什么现在学jQuery选择器还不过时“新项目谁还在用jQuery”这个话题我身边每隔一段时间就会被拿出来吵一次。尤其这两年前端框架越来越重动不动就是脚手架、组件化初学者很容易产生一种错觉jQuery已经是老古董没必要浪费时间。但只要你碰过一次老项目的维护或者在兼容要求比较高的活动页里写过脚本就会理解“jQuery还有必要学吗”这个问题不能一概而论。而即便抛开维护场景jQuery 选择器本身也值得花时间吃透因为它是理解“如何精准定位页面元素”的最直接入口。先摆一个事实很多仍在稳定运行的后台管理系统、电商平台活动页、旧版 CMS内部还是大量 jQuery 代码。就算你用 Vue 或 React 重写了大部分功能只要还保留着 Datatables、EasyUI、日期选择器这类老牌插件就免不了跟 jQuery 对象打交道。这时候懂不懂选择器直接决定你能不能在三分钟内改完一个需求还是连排查都要翻半天文档。更重要的是jQuery 选择器的语法几乎沿用了 CSS 选择器规范又额外扩展了:eq、:contains、:first这类方便伪类。你把这套规则学扎实后面切换到原生querySelectorAll或者去理解 CSS 选择器的优先级都非常顺滑。可以说选择器是 jQuery 里最值得背下来的一块知识性价比极高。1.2 一条适合新手的学习路径和优先级有些人学 jQuery 喜欢一上来就翻 API 文档看事件、看动画、看 Ajax结果用到选择器的时候总是临时查写出来的代码又长又绕。我的建议是把它当成一条完整链路的前置环节选择器 → DOM 遍历与操作 → 事件 → 动画 → Ajax → 组件封装。选择器这一步又可以按下面的分类顺序去消化阶段学习内容典型写法解决的问题基础选择器id、class、标签、通配、并集$(#id)$(.class)$(p)快速定位一个或一类元素层级选择器后代、子元素、兄弟$(ul li)$(ul li)$(h3 p)按 DOM 结构关系定位元素筛选选择器位置、子元素位置、内容、属性$(li:first)$(li:first-child)在集合内进一步过滤目标这三类掌握以后再去看.find()、.children()、.filter()这类遍历方法就会觉得顺理成章。你甚至可以这样理解选择器负责“找到起点”遍历方法负责“在起点周围进一步移动”两者经常搭配使用。下面我按这三个分类逐个讲并把实际项目里容易踩的坑标出来。2. 基础选择器写 jQuery 的本能反应2.1 ID 选择器与类选择器ID 选择器是 jQuery 里查询效率最高的因为底层可以直接映射到document.getElementById。写法就是$(#id)#后面对应元素的 id 属性值。类选择器用.class最终拿到的是一组元素哪怕页面里只有一个元素匹配外层也是一个类数组结构的 jQuery 对象。// 选中 id 为 userName 的元素 var $name $(#userName); // 选中所有 class 包含 menu-item 的元素 var $menuItems $(.menu-item);这里有个新手经常犯的错拿到类选择器结果以后直接调.value取输入框内容。jQuery 对象不是原生 DOM取输入框值要用.val()取文本用.text()取属性用.attr()。如果确实拿到的是原生 DOM应该写$(.menu-item)[0].value或者说用.get(0)。还要注意id 在页面中必须是唯一的。后端模板引擎、服务端控件渲染时偶尔会生成带冒号的 id比如ctl00_ContentPlaceHolder1_txtName这种倒还好但如果 id 里真的包含:直接$(#id:name)会被解析成伪类必须转义成$(#id\\:name)。顺带提一句ASP.NET GridView 这类控件经常会动态生成复杂 id所以很多同学习惯用$(input[typetext])这种属性选择器去规避特殊字符问题。两个小提醒同一个选择器如果会被多次使用先缓存成变量比如var $box $(#box);避免每次重复查询。ID 前面不要画蛇添足写标签名比如$(div#box)能跑但没必要还多一次过滤。2.2 标签选择器与通配选择器标签选择器直接写元素名例如$(div)、$(li)、$(input)底层借助getElementsByTagName或者querySelectorAll来实现。当你想为某种标签统一加事件、统一加样式时非常省事。// 所有 tr 加一个 class $(tr).addClass(data-row); // 所有文本框先清空 $(input[typetext]).val();标签选择器的问题是匹配范围大尤其页面里 div 和 span 到处都是如果只是要给某个区域内的标签加样式一定要限定上下文。比如$(#main li)远好于$(li)。通配选择器*匹配的是所有元素威力大但代价也大。$(*)会遍历整棵 DOM 树性能损耗明显。实际开发中几乎不会单独用偶尔会出现在组合选择里比如$(#box *)选中某个容器里的全部子子孙孙但能不用就尽量不用。2.3 并集选择器与基础组合写法并集选择器用逗号把多个选择器串起来表示“匹配其中任意一个”。这个规则从 CSS 到 jQuery 都一致。// 同时选中所有 h2 和 .title 以及 #footer $(h2, .title, #footer).css(border, 1px solid #eee);要注意返回结果的顺序并不是按照你写选择器的顺序而是按照元素在文档中出现的顺序排列。这个细节在做索引过滤时很重要如果你:eq(0)拿到的不是自己以为的那个选择器里的第一个先想想元素顺序。并集选择器最常见的场景是多个入口做同样的事比如“关闭按钮”和“弹窗遮罩”都要触发关闭逻辑$(.btn-close, .modal-mask).on(click, function () { $(#modal).hide(); });基础组合中还有一个容易被忽略的写法上下文参数。$(li, #list)等价于$(#list).find(li)。这类写法在插件源码里很常见因为它可以让你在不额外缓存父元素的情况下快速把范围锁到某个容器内部。3. 层级选择器用结构关系定位元素3.1 后代选择器一个空格代表“任意子孙”后代选择器用空格表示作用是选中某个元素内部所有满足条件的子孙节点不只是儿子还包括孙子、重孙子。它是实际项目里用得最多的层级选择器因为大多数时候我们需要的是容器内部的某类元素而不是精确到第几层。div idbox p直接段落/p section p嵌套段落/p /section /div// 会选择两个 p 元素包括嵌套在 section 里面的那个 $(#box p).css(color, red);这个“包含所有子孙”的特性既是优点也是坑。比如一个商品列表页你在ul上写了$(ul a)去绑点击但如果a又有自己的子元素图标点击事件照样会触发再比如你要统计某个容器内直接有几个子节点用后代选择器就会多算嵌套层级这时候就该换用子元素选择器。3.2 子元素选择器只认亲儿子子元素选择器用连接只匹配直接子元素不会再往下钻。它的语法和 CSS 完全一致很多场景下能帮你避免误伤深层节点。还是上面那段 HTML// 只选中 section 外面的那个 p $(#box p).css(color, red);在这里被选中的只有 div 的直接子元素 p嵌套在 section 里的 p 会被忽略。这在设计下拉菜单、标签页这类层级分明的组件时特别重要。我自己的经验是能用的地方就别用空格。一方面是为了减少匹配范围、提升一点性能更重要的是语义更清楚——你写$(#box p)时读代码的人一眼就知道操作目标是直接子节点写$(#box p)时还得去猜你是不是真的想照顾到深层元素。顺带说一个性能上的贴心理解后代选择器需要往树的深处持续扫描子元素选择器只需检查一层父子关系所以同样的结构下通常比空格更轻快。3.3 相邻兄弟与后续兄弟 和 ~兄弟选择器主要处理“同一父元素下的同级元素之间的关系”。相邻兄弟选择器用它只会选中紧跟在指定元素后面的那个兄弟元素通用兄弟选择器用~会选中指定元素后面的所有兄弟元素。h3文章标题/h3 p段落A/p p段落B/p$(h3 p).text(只匹配段落A); $(h3 ~ p).text(匹配段落A和段落B);开发中比较典型的用法是 hover 某个按钮时显示或激活紧随其后的面板。比如$(.btn-open .dropdown).addClass(show);这种写法比给每个按钮都绑定一个带索引的 id 干净得多。配合事件委托时兄弟选择器也能减少不少临时变量。需要注意和~都只向后匹配不会往前找。所以如果你需要“前面的兄弟元素”jQuery 里没有对应的选择器得用.prev()方法。4. 筛选选择器按位置、状态和内容找元素4.1 位置筛选first、last、eq、gt、lt位置筛选选择器是 jQuery 相对原生 CSS 选择器扩展得比较多的部分它的作用是站在“匹配结果集合”的角度继续过滤。:first匹配集合中的第一个元素:last匹配集合中的最后一个元素:eq(index)匹配集合中索引为 index 的元素索引从 0 开始:gt(index)匹配集合中索引大于 index 的元素:lt(index)匹配集合中索引小于 index 的元素:even匹配索引为偶数的元素注意这里的偶数索引从 0 开始:odd匹配索引为奇数的元素$(li:first).addClass(current); // 第一个 li $(li:eq(2)).text(第三个 li); // 索引 2 对应第三个 $(li:gt(1)).hide(); // 索引 1 之后的 li 全部隐藏 $(li:lt(2)).hide(); // 索引 0 和 1 的 li 隐藏这几个选择器在做表格分页、轮播、列表高亮时非常顺手。比如要给表格加斑马纹除了用 CSS 的nth-child(even)在旧项目里也可以这样写$(#tableBody tr:even).addClass(even-row);这里有个特别容易踩的坑:even和:odd是以当前匹配集合的索引来计算的不是以子元素在父容器里的顺序计算的。假设你先把选择器范围缩小到了$(.list li:visible)那么“第偶数个可见元素”和“DOM 里的第偶数个 li”就是完全两回事。4.2 子元素位置筛选first-child 与 nth-child 的区别上一节的:first是“匹配集合中的第一个”而:first-child强调的是“父元素的第一个子节点”。这两个名字就差一个词含义差得很远。看一段例子ul classlist liA/li liB/li /ul ul classlist liC/li /ul$(ul.list li:first).length; // 1取所有 li 里的第一个 $(ul.list li:first-child).length; // 2A 和 C 都是各自父元素的第一个子节点热词里经常看到“jquery 第一个子元素”大家搜的大概率是first-child而不是:first。当你希望“每个分组里的第一个”都被选中时用:first-child当你只想要“所有匹配结果里的第一个”时用:first。同理:last-child、:nth-child(n)也都是基于父元素的子节点位置来计算的。// 每个表格行的第一个单元格加粗 $(tr td:first-child).addClass(strong); // 选中每个列表的第二个子节点注意 nth-child 从 1 开始 $(ul li:nth-child(2)).css(color, #c00);:nth-child还支持odd、even以及公式写法例如:nth-child(2n1)这套语法和 CSS 规范性一致。用它的好处是天然跟元素在结构中的位置绑定即便前面同样有多个容器也不会串位。4.3 内容与状态筛选contains、empty、visible、checked除了位置jQuery 还能按内容、显示状态和表单状态来筛选元素。// 按文本内容过滤 $(p:contains(报错)).addClass(error-text); // 空元素没有子节点也没有文本 $(div:empty).hide(); // 包含某个子元素的父元素 $(.card:has(.btn-danger)).addClass(warning-card); // 可见不可见 $(#tips:hidden).fadeIn(); $(input:visible).focus();:contains非常实用但有两个限制。一是参数里如果文本含有引号匹配会容易出错需要仔细转义二是它执行的是子字符串匹配不是精确匹配所以:contains(媒体)也会匹配“新媒体运营”。想要精确匹配文本建议还是用原生遍历或写个过滤器函数。:visible和:hidden的判断逻辑也不算直观。jQuery 判断隐藏元素大致依据是 display 为 none、type 为 hidden、宽高为 0或者父元素已经隐藏。visibility: hidden在多数版本里也会被认定为隐藏但opacity: 0的元素不算隐藏。写自动化脚本时要特别留意不要以为透明元素就是隐藏。表单类状态选择器也很常用$(input:checked).val(); $(option:selected).text(); $(input:disabled).prop(disabled, false);4.4 属性筛选选择器精确匹配你的钩子属性选择器是筛选选择器里的一组重要分支它不靠位置、不靠文本而是看元素的属性特征。常见写法有五种[name]带有指定属性名即可[namevalue]属性值精确等于 value[name^value]属性值以 value 开头[name$value]属性值以 value 结尾[name*value]属性值包含 value// 找所有以 user 开头的 input $(input[name^user]).css(border, 1px solid red); // 找所有 pdf 链接 $(a[href$.pdf]).addClass(pdf-icon); // 找所有带>$(#productTable).on(mouseenter, td, function () { var fullText $(this).text().trim(); // 超过 20 个字符才给 title避免无意义提示 if (fullText.length 20) { $(this).attr(title, fullText); } });这里的#productTable td是后代选择器配合事件委托即使后面的数据是 Ajax 动态加载进来的也能正常触发。这个场景典型体现了选择器的组合价值先定位表格再通过事件委托聚焦到单元格。5.2 案例Tab 切换联动内容区写 Tab 组件时新手常常写出大量eq(i)配合循环的代码其实选择器加链式方法就可以做得很干净。$(.tab li).on(click, function () { var index $(this).index(); $(this) .addClass(active) .siblings() .removeClass(active); $(.tab-content) .eq(index) .addClass(active) .siblings() .removeClass(active); });这里的$(.tab li)用子元素选择器避免内部嵌套结构影响点击目标.index()方法拿到当前 li 在兄弟节点中的索引内容区用.eq(index)配合索引选中对应块。整个过程没有写复杂循环读起来一目了然。5.3 选择器的性能注意点与最佳实践选择器性能是一个老生常谈但又容易被忽视的点。以下几点是我在实际项目里反复验证过的优先用 ID 选择器定位容器再用.find()往下找比写超长后代选择器更清晰。多次使用的查询结果一定缓存成变量不要每次用到都重新$()。少用通配选择器也少用:hidden、:visible这类全页面范围内过滤的伪类。非要复杂过滤时可以用.filter()方法配合函数可读性通常比堆一长串伪类更好。// 不推荐长选择器写一堆 $(div#wrapper .content ul li:visible:first); // 推荐分步定位 var $visibleItems $(#wrapper .content ul li).filter(:visible); $visibleItems.eq(0).addClass(current);jQuery 底层用的是 Sizzle 选择器引擎原生querySelectorAll能支持的选择器它会优先交给浏览器原生解析而那些原生不支持的扩展伪类比如:eq、:contains它就会退回到 JavaScript 遍历过滤。所以不是所有选择器都一样省钱越贴近 CSS 标准的选择器性能越稳定。6. 常见问题与排查心得6.1 选择器找不到元素先检查这几件事我在帮同事排查问题时发现选择器“没效果”的原因通常不在选择器语法本身而在执行时机和对象类型。第一代码是不是在 DOM 加载前就执行了。如果脚本写在head里直接$(#box)拿到的必然为空。解决方案是把代码包在$(function () {})里面让页面 DOM 就绪后再执行。第二是不是把 jQuery 对象和原生 DOM 混用了。$(#id)返回的是 jQuery 对象你要在控制台打印看看结构而不是直接打印$(#id).value。判断一个元素到底存不存在标准写法是$(#id).length 0。第三选择器里的大小写和空格是否准确。class 名和 id 名是区分大小写的HTML 标签名虽然不区分但选择器里的属性值区分。还有空格表示后代如果你写的选择器是$(.menu :first)中间这个空格会让:first变成所有后代元素中的第一个往往不是你要的菜单自身。6.2 动态加载的内容为什么绑定不上事件这个坑十个新手九个踩。你用一个 id 选择器找到按钮然后.on(click)绑定事件按钮一开始不存在而是 Ajax 返回后才插入页面那事件自然绑不上。解决方案是事件委托把事件绑定到父容器上再通过选择器过滤触发目标$(#tableBody).on(click, tr[data-id], function () { // 即使 tr 是后来动态生成的也能触发 });选择器在这里承担的责任是“过滤触发源”不是“直接绑定对象”。只要父容器在页面初始时就存在后续动态插入的元素都能被正确识别。6.3 我的三个经验技巧工具再简单也经不起天天用用久了自然会有一些自己的习惯。这三个经验是我使用 jQuery 比较高频的技巧一是能用data属性钩子就别硬扣 class。比如行选中、状态切换这类需求优先给元素加>$(ul.nav) .find(li.active) .addClass(current) .end() .addClass(has-active);三是在调试阶段多利用console.log($(#xxx).length)来验证选择器命中了几个元素而不是盯着页面看效果。页面效果没出现的时候往往是选择器没匹配上不是 jQuery 每个方法都失效了。7. 最后分享一个我自己的使用习惯文章写到这里内容基本已经讲完最后想分享的是我在实际开发中的一个判断标准能用简单选择器解决的问题绝对不用复杂的扩展伪类能用一次查询加链式方法完成的绝不写第二遍。选择器只是工具写得清晰才能真正加快开发速度。如果新项目里还在纠结要不要用 jQuery我的看法是先看你的浏览器支持目标再说。但如果你只是想快速理解 DOM 与 CSS 选择器之间的关系jQuery 选择器依然是一本很直观的“教科书”。把基础选择器、层级选择器、筛选选择器这三块吃透后面的路会顺很多。
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。