ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

jQuery核心实践:选择器、第一个子元素与name获取全解析

jQuery核心实践:选择器、第一个子元素与name获取全解析 刚入门前端的时候纠结过一个问题明明原生 JavaScript 写得好好的为什么非要去学 jQuery等到真正接手一个老项目面对十几年前的代码库和一堆$符号满天飞的页面时才明白这套东西到底有多普及。本文不谈玄虚概念直接从 jQuery 的核心知识点入手重点拆解几个热搜问题——jQuery 的第一个子元素怎么选、根据 name 获取对象怎么写、以及日常开发里最容易踩的坑结合大量实操示例讲清楚。无论你是准备面试、维护老项目还是单纯想把前端基本功补一补这篇内容都能直接用得上很像当年师傅带着过一遍代码的节奏不需要你有多深的 JavaScript 基础跟着敲一遍基本就会了。1. 内容整体设计与思路拆解先说个实在话jQuery 到今天还有大量存量项目在跑从后台管理系统到各种企业门户甚至在部分用 Vue 或 React 构建的项目里偶尔也能看到有人图省事引了 jQuery 做 DOM 操作。所以你不能说这东西已经过时只能说现在它的定位变了——从一个前端开发者的“主力框架”变成了一个“兼容层”和“工具包”。1.1 核心需求解析大家学 jQuery 最常搜的问题集中在几个点上选择器、属性操作、遍历、事件、动画、AJAX。其中选择器和属性操作又是日常写业务代码时使用频率最高的一部分。而热词里的“jQuery 第一个子元素”“jQuery 根据 name 获取对象”恰好都属于这个范畴。“第一个子元素”解决的是筛选问题——拿到了一个父元素集合怎么精确锁定内部第一个符合条件的子节点。“根据 name 获取对象”解决的是定位问题——表单场景下怎么通过表单元素的 name 属性快速拿到值、操作选中状态。这两个问题看似简单实际用起来却有几个容易混淆的细节:first-child和:first有什么区别:eq(0)什么时候才适合用[namexxx]和.filter([namexxx])是一样的吗这篇文章会逐个说清楚。1.2 为什么选这些知识点展开筛掉高大上的框架对比剩下的都是“每天都会用到的真问题”。我见过不少新人一上来就啃 jQuery 源码或研究插件机制反而等面试官问“怎么按 name 获取表单对象”的时候愣住半天。核心知识点就应该先围绕以下三块打牢选择器体系jQuery 所有操作都是从选择开始的选对了后面全部顺畅。遍历与筛选动态页面里元素是不断变化的筛选能力直接决定代码健壮性。属性与表单操作业务系统离不开表单知道怎么拿值、设置值、触发校验才是落地的本事。把这些基石打牢之后事件绑定和 AJAX 都可以顺着同一套逻辑延展出去后面学什么都快。2. 核心选择器与第一个子元素的实操拆解jQuery 最出彩的地方就是选择器。它基于 CSS 选择器语法并做了大量扩展让“找到元素”变成了一条简短表达式。今天我给新人讲代码从来都让他们先把选择器体系吃透因为后面所有链式操作都在这个基础上跑。2.1 基础选择器回顾在最底层你需要分清这几类ID 选择器$(#userForm)性能最好唯一。类选择器$(.input-item)返回一组元素。标签选择器$(input)直接按标签名捞。属性选择器$(input[nameusername])用方括号精确匹配属性。这些基础写法网上到处都有但我想强调一个点用选择器时一定要明确返回的是单个元素还是 jQuery 对象集合。$(#id)也返回的是 jQuery 对象只是这个集合只有一个元素。因此你拿到结果后如果直接.value是拿不到的得用.val()或.attr()这是个新人高频翻车点。2.2 第一个子元素:first-child与:first的区别这个问题值得单独拿出来说因为我发现很多人搜了答案也不知道为什么答案长那样。先说结论:first-child是 CSS 伪类匹配规则匹配的是“某个父元素下的第一个子元素”。它不看你在选择器里筛的是什么而是看元素在父节点里的物理位置。:first是 jQuery 提供的扩展伪类等价于.eq(0)匹配的是匹配集合中的第一项和它在 DOM 树里的位置没直接关系。举个例子结构如下ul classlist li classitem第一项/li li classitem第二项/li li classitem第三项/li /ul这时候$(li:first-child)会选中“第一项”因为它确实是在父节点里的第一个子元素。但假如页面上有两个.list每个 list 里都有 li那$(li:first-child)会选中两个 li——每个列表的第一个子节点都满足条件。而$(.item:first)永远只返回一个元素就是整个匹配元素集合里的第一项。所以实际落地时你要先想清楚一个问题我只想要一个结果还是所有父元素下各自符合条件的第一个场景推荐写法说明整页匹配元素的第一个$(.item:first)或$(.item).eq(0)与 DOM 位置无关只与匹配顺序有关每个父元素下的第一个子元素$(.list li:first-child)严格按父子关系筛选特定父元素下第一个子元素$(#list li:first-child)用 ID 收窄范围性能更好某个父元素下的第 N 项$(#list li).eq(2)从 0 计数适合动态索引:first-child之外还有:last-child、:nth-child(n)、:only-child都可以按同样的思路去理解。掌握这个规律后写动态列表里的“第一个元素加高亮”“最后一个元素加分割线”都没压力。2.3 常见误用与坑误用一$(li:first-child)想要“整个页面中第一个 li”但页面若有多个 ul会返回多个元素因为每个 ul 的第一个 li 都命中。误用二$(li:first)想要“每个 ul 下的第一个 li”它会只返回一个达不到循环处理的目的。误用三把:first-child和:first-of-type混为一谈。前者是“父元素下的第一个子元素”后者是“父元素下该标签类型的第一个子元素”。比如父元素里第一个子节点是span用p:first-of-type时它会跳过 span 找 p。早年在这上面吃了不少亏每次排查样式都以为是 CSS 优先级问题结果是对伪类理解偏了。2.4 实操给列表第一个子元素加样式写一个完整小例子直接抄就能用ul classlist idfirstDemo li常规项 1/li li常规项 2/li li常规项 3/li /ul script srchttps://code.jquery.com/jquery-3.6.0.min.js/script script $(function () { // 只给第一个 li 加红色 $(#firstDemo li:first-child).css(color, #c00); // 如果你想给每个 ul 下的第一个 li 都处理就记得选择器别限制死 id // $(ul li:first-child).css(border-top, 1px solid #eee); }); /script这种写法在渲染列表页、消息通知页等场景非常常用。由于选择器本质返回的是 jQuery 对象你还可以直接继续链式调用.addClass()、.attr()、.data()等不用重复获取元素代码也干净很多。2.5 进阶结合遍历更灵活只知道选择器还不够因为动态生成的内容经常让你“选不中”。比如列表之后又从接口追加了新数据那新数据在 DOM 里也是 li选不选得到要看选择时机。此时建议用事件委托或遍历方法。遍历方法里最常用的是.each()、.find()、.children()和.filter()这几个.children()只获取直接子元素。.find()会向下搜索所有符合条件的后代元素。.filter()在当前匹配结果中继续筛选。.each()是遍历处理每个元素都执行回调。举个例子拿到一个列表容器之后想处理每个列表的第一个子元素你可以这样$(.list).each(function () { $(this).find(:first-child).addClass(first-item); });这里的:first-child仍然是按父子关系找但因为已经用.each()拆开每个.list单独处理取到的就正好是各自列表里的第一项这种组合思路比硬写ul li:first-child更灵活也更好控制条件。3. 根据 name 获取对象的正确姿势业务开发里最常接触的页面是什么表单页。用户注册、数据录入、筛选条件、后台配置全是表单。而表单元素最稳定的标识很多时候不是 id而是 name。因为 id 讲究唯一动态生成的表单片段里 id 很容易重复name 却常常保留着和后端字段一致的名字成了前后端联调的桥梁。3.1 属性选择器的写法“根据 name 获取对象”实际上就是利用属性选择器// 写法一通用属性选择器 $(input[nameusername]).val(); // 写法二如果知道具体标签类型 $(input[nameusername]).length; // 看看找到了几个这里有几个非常容易踩的坑我边说边写上解决方法。坑一忘了加引号$(input[nameusername])多数浏览器也能跑但遇到 name 里有特殊字符时就会出问题。比如user-address、user[email]这类名字不加引号直接报错或返回空集合。正规做法永远是加引号这是保证安全和稳定性的最低成本操作。坑二属性值大小写HTML 属性一般建议小写但数据从后端回填或模板渲染时name 偶尔会有大小写混合比如userName。jQuery 属性选择器是区分大小写的$(input[nameusername])匹配不到nameuserName的表单。写代码前先统一规范页面调试时也可以先console.log($(input).length)确认元素到底加载没有。坑三动态生成的表单用模板渲染出来的 input如果你在渲染之前执行了查询返回结果就是空的。这不是选择器写错了而是执行时机问题务必把代码放到 DOM 渲染完成之后再调用最保险的就是放进$(function(){})或$(document).ready的事件里。3.2 综合场景按 name 处理一组数值实际开发中name 相同的表单元素可以做组。比如一组都是 checkbox 的选项name 全叫hobby。这时候按 name 获取对象返回的是一个集合处理时需要遍历form idhobbyForm input typecheckbox namehobby valuereading 阅读 input typecheckbox namehobby valuesport 运动 input typecheckbox namehobby valuemusic 音乐 /form button idgetHobbyBtn获取选中的爱好/button$(function () { $(#getHobbyBtn).on(click, function () { var selected []; $(input[namehobby]:checked).each(function () { selected.push($(this).val()); }); console.log(selected); }); });这里出现了一个新知识点:checked伪类。它和前面讲的:first-child一样都是筛选条件但筛选依据是元素的选中状态。这种写法在动态表单、批量操作、权限勾选等场景下非常常见也是面试里很喜欢问到的点。3.3 结合.filter()与.serialize()的高效用法有些情况下直接选择器不好写比如 name 带动态后缀或者表单字段是拼接出来的。此时可以先用范围选择器把容器里的表单元素捞出来再用.filter()按 name 进一步过滤var formItems $(#dynamicForm).find(input, select, textarea); var userField formItems.filter([name^user_]);这用到了 CSS 的属性前缀匹配符^意思是以某个字符串开头。如果性能要求更高完全可以把范围缩小到具体的 form id。另外不要忘记.serialize()方法。它能把表单里所有带 name 的元素按键值对序列化成usernameabcage20格式非常适合 AJAX 提交。它拿值的前提就是元素必须有 name 属性这也是强调“根据 name 获取对象”的原因之一——没有 name.serialize()完全不理你。4. 事件绑定、动画与 AJAX 核心串联结构和选择器搞定了接下来是页面交互。jQuery 的事件绑定和动画看似基础但很多“疑难杂症”都来自事件绑定的细节。这里把最重要的几个点串一遍。4.1 事件绑定on与off的工程意义你现在看到的大多数 jQuery 教程都会用.click(function(){})这种写法它简洁但有个致命弱点不利于统一管理和解绑。工程上更推荐的是.on()方法$(#saveBtn).on(click, function () { // 保存逻辑 });.on()的好处很多但最关键的是事件委托。动态添加的元素要注意直接在文档加载完成后给元素绑事件后来加进来的新元素不会自动带事件。举个例子一个任务列表点击任务项能弹出详情。如果使用:$(.task-item).on(click, function () { ... });那这个事件只绑到了初始加载的元素上。如果后面通过 AJAX 又插入了新任务项新元素上是没有事件的。正确写法是把事件委托给稳定的父容器$(#taskList).on(click, .task-item, function () { // 这里的 this 就是点击的那个 .task-item });用事件委托的好处是父容器一直都在不需要重新绑定性能上通常也更高。现在搜索“jQuery 动态元素点击没反应”基本都指向这个问题。4.2.off()避免重复绑定另一个高频问题是“按钮点击一次执行了两遍”。原因多半是同一个事件被绑定了两次。比如你在某个函数里反复调用$(#btn).on(click, handler)每调用一次就多一个监听。解决办法是在绑定前先解绑$(#btn).off(click).on(click, handler);我把这套规则总结为“先 off 再 on”。说起来简单但在多人协作的项目里非常实用因为你可能不知道哪个同事在哪个模块里已经绑过事件。4.3 动画的常用方法jQuery 动画方法太多但业务里最常用的就是.show()、.hide()、.fadeIn()、.fadeOut()、.slideDown()、.slideUp()这几个。它们都有个共同点可以接收速度参数和回调函数。$(#tipBox).fadeIn(300, function () { // 动画结束后执行 });回调函数的意义在于你可以在动画完成后再做后续逻辑避免动画进行中读取样式拿到过渡值。比如动画完成后才能移除元素或者动画完成后再请求接口这些需求都能用回调安全搞定。另外有个技巧.animate()可以自定义动画但做复杂动画序列时链式调用或者使用回调嵌套会导致一长串“回调地狱”。更好用的方式是使用.delay()延迟配合队列执行$(#box) .slideDown(300) .delay(800) .fadeOut(400);这种写法和链式调用一样自然可读性也不错是新人也容易上手的动画队列思路。4.4 AJAX 请求的现状与封装$.ajax是曾经的灵魂但现代开发里大家更多用fetch或 axios。不过老项目里离不开 jQuery AJAX而且它的很多选项用起来确实方便。看一个典型场景登录表单提交。$(#loginForm).on(submit, function (e) { e.preventDefault(); var formData $(this).serialize(); $.ajax({ url: /api/login, method: POST, data: formData, dataType: json, success: function (res) { if (res.code 0) { location.href /dashboard; } else { alert(res.msg); } }, error: function () { alert(网络异常); } }); });关键点有三个一是e.preventDefault()阻止默认提交这是原生传统表单的常见改动二是$(this).serialize()一行就能把表单数据取出来三是dataType: json强转返回类型避免接口返回字符串时处理出错。如果多个请求共用 header比如接口需要 token建议用$.ajaxSetup({ headers: { X-Token: token } })统一配置不用每个请求都写一遍。这也是我在老项目里最常用的提效方式。5. 常见问题与排查技巧实录和认知相反jQuery 出问题往往不是 API 背得不够多而是环境细节导致的。我把工作和维护老项目时踩过的坑按出现频率整理成一份速查表希望能让你少走一些弯路。5.1 常见问题速查表问题现象常见原因解决方案$未定义jQuery 库没加载或加载顺序不对在控制台确认typeof jQuery放到 DOM 引入顺序正确的位置元素找不到返回空集合脚本写在 DOM 渲染之前放进$(function(){}):first-child元素比预期多每个父节点里各取了一个先匹配的明确你的预期是全部父节点还是一组结果里的第一个改用.eq(0)input[namexxx]取不到属性值大小写敏感或引号问题统一小写属性值加引号动态添加的元素点击无效事件绑定没使用委托改成$(父容器).on(click, .子元素, handler)按钮点击事件重复执行事件重复绑定先.off()再.on().val()取不到内容元素不是表单控件div、span这类元素没有val()用.text()或.html()AJAX 请求返回字符串但按对象使用没指定dataType: json请求参数加上dataType: json5.2 我亲历的两个典型排查案例案例一列表第一项样式死活加不上有一次给一个报表页面加“默认选中第一行”的功能代码写的是$(.report-row:first-child).addClass(active)。结果控制台一查加不上或者加错了地方。后来排查发现.report-row并不是父元素的第一个子节点它前面还有个隐藏的占位div。:first-child严格检查物理位置所以没匹配上。换成$(.report-row).first().addClass(active)问题就解决了。这个案例带来的启发凡是和“优先级”相关的逻辑先确认 DOM 结构别想当然。案例二按 name 获取 checkbox 时数组越界一个权限配置页面每行用户都有几个 name 为perm_read、perm_write的 checkbox。后端要求最终回传一个拼接字符串我用$(input[nameperm_read]:checked)去取结果发现第一次正常第二次打开时带上了一组重复勾选。原因很荒谬页面里所有行共用同一个 name但不同行的 ID 和状态是独立的我却没在一开始清空上一行遗留的选中状态。后来改成在每次打开弹窗时先调用$(#permForm input[typecheckbox]).prop(checked, false)重置状态再回填数据问题就干净了。正确业务往往需要“先重置再赋值”这个思路在编辑弹窗、详情回显场景里都非常通用建议直接养成习惯。5.3 调试技巧与习惯调试 jQuery 代码时最高效的三个习惯控制台直接跑选择器。打开浏览器的Console直接输入$(input[nameusername])回车看看返回了什么。这一步比反复刷新页面强得多。console.log别囤着。看到关键分支就输出当前值比如console.log($(this).val())。尤其在使用回调函数时this 指向经常是个迷多打印几次就有数了。注意链式调用的返回值。jQuery 设计里很多方法改了元素的状态但返回的还是原 jQuery 对象可以继续.end()回到上一层也可以接新方法。清楚每一步返回什么比死记 API 更管用。5.4 顺手积累的几个实用小技巧除了前面讲的我平时写代码还留着几个固定小工具表格隔行变色$(#table tr:even).addClass(even-row):even和:odd从 0 开始计数隔行处理很顺手。一键全选利用$(input[nameids]).prop(checked, true)批量操作界面几乎都能用上。表单验证提示定位到某个 name 所在容器再控制显隐用$(input[nameemail]).closest(.form-item).addClass(has-error)比逐条写 id 效率高很多。按钮防重复提交点击后立即禁用请求完成再恢复$(#submitBtn).on(click, function () { var btn $(this); btn.prop(disabled, true); $.ajax({ // ... complete: function () { btn.prop(disabled, false); } }); });第 4 条在半秒内连续点击提交的场景下非常有用能让接口少承受很多无意义的重复请求。6. 最后从实战角度说几点体会写了几年 jQuery 相关代码维护过几个“年龄不小”的老项目最大的体会是jQuery 并不像网上说的那么没用它的设计思路在某些场景下甚至还是很舒服的——选择器简单直接、链式调用读起来顺畅、AJAX 写法少而且参数统一。对于老项目的日常维护、临时活动页、管理后台这类“数据展示表单提交”的页面jQuery 完全够用。当然如果是新项目我也不会推荐再用 jQuery 起步。现代前端框架的数据驱动思维确实更利于复杂状态管理。但学习 jQuery 的过程并不会白费因为 DOM 操作、事件机制、选择器这些底层概念是相通的。你先把 jQuery 里的“选择-操作-绑定-请求”这套流程跑通再去看 Vue 或 React 的模板语法和生命周期思路反而更容易拐过来。这篇内容从 jQuery 核心选择器、第一个子元素、按 name 获取对象一直讲到事件绑定和 AJAX都是实际开发里最高频的那批问题。后续你可以沿着这个方向继续扩展each与map的区别、prop与attr的边界、AJAX 异常处理、插件封装思路等每一个拆开都够单独写一篇。希望这篇能帮你把基础打得扎实一点少走点我当年走过的弯路。最后分享一个我常用的训练方法随便找一个老的后台管理系统页面试着用原生的 JavaScript 把页面里所有表单数据取出来然后再用 jQuery 实现一遍。做完这个对比你就知道为什么当年 jQuery 能火遍大江南北也更能理解现在的框架到底帮我们解决了什么问题。
返回列表