2026年为什么还要用jQuery?它没死,只是成了前端基本功

2026年为什么还要用jQuery?它没死,只是成了前端基本功
1. 为什么2026年还要用jQuery——先把这个想清楚再往下学先说个可能有些反常识的结论jQuery没有死它只是从“主角”变成了“熟练工”。这几年新入行的前端基本一上来就是React或Vue,很多人甚至没写过几行原生JavaScript就直接进框架了。但等你真正进了项目组尤其是接手老系统、维护后台管理端、对接第三方插件时会发现jQuery依然大量存在。我见过不少刚入职的同学看到项目里$(document).ready()就慌了因为学校没教、面试也没考。jQuery能扛到今天核心原因有三点兼容性覆盖极广IE老版本环境下其它框架可能直接白屏jQuery 1.x系列还能稳定运行API设计极其简洁选择器语法已经成为前端开发者的共同语言后来CSS选择器和querySelectorAll的普及一定程度上也是被jQuery带起来的生态插件存量巨大时间插件、表格插件、轮播插件、富文本编辑器几十万套成熟方案都是基于jQuery封装的。所以这篇东西适合谁看如果你是刚学前端、想打牢DOM操作和事件处理基本功的初学者jQuery是很好的练习载体如果你要维护老项目那更是刚需就算你已经在用Vue或React理解jQuery的设计思路对你看源码、写自定义指令或Hook也有帮助因为它把很多浏览器差异和DOM操作细节封装到了极致读它的源码就是一个提升过程。我在实际项目中还发现一个很有意思的现象很多“前端面试题”都会拿jQuery出来对比原生API问你$(.class)和querySelectorAll的异同、$(document).ready和window.onload的区别。这说明行业默认你应当具备jQuery的基础认知。与其面试前临时抱佛脚不如系统地过一遍。下面我不按官方文档的顺序一章一章念经而是按“高频使用场景→真实项目踩坑→性能与排查”这条实战主线来讲。每个部分都会给可复制的代码和当时为什么这么写的分析不是网上一抓一大把的那种demo拼凑。2. 从原生JavaScript到jQuery——理解选择器与链式调用的设计哲学2.1 选择器为什么会成为jQuery的灵魂jQuery最出名的就是$()工厂函数本质上是把document.querySelectorAll那一套选择器逻辑做了封装同时兼容老浏览器。你写$(#id)、$(.class)、$( input[typetext])它内部都会统一处理。早年原生JavaScript在IE里获取元素的方式混乱getElementById、getElementsByClassName、getElementsByTagName各自为政jQuery一套$()全搞定这就是它当年横扫前端的原因。但你要注意一个细节$()返回的不是原生DOM元素而是一个类数组的jQuery对象。它内部维护了匹配到的所有元素可以用[0]或.get(0)取回原生DOM。这个设计带来的好处是所有jQuery方法都可以直接作用在一组元素上不需要手动循环。比如要给页面上所有.item加红色背景// 原生写法 var items document.querySelectorAll(.item); for (var i 0; i items.length; i) { items[i].style.backgroundColor red; } // jQuery写法 $(.item).css(background-color, red);这不仅仅是代码行数减少的问题而是思维方式的转变——从“遍历分别处理”变成了“集合级操作”。你不需要关心循环不用管索引jQuery内部帮你处理了全部细节。2.2 链式调用为什么它能减少性能损耗jQuery对象上的大部分方法会返回操作后的自身这就是链式调用的基础。你可能看过这种代码$(.item) .addClass(active) .css(color, #fff) .attr(data-status, on) .append(span已激活/span);这样写的好处不只是优雅更重要的是避免反复查找DOM。如果你用拆开的方式写每一步都要重新执行$(.item)意味着每次都重新走一遍选择器查找。而链式写法只在最开始查找了一次后续操作都在内存中的jQuery对象上进行。一个页面操作多了以后这个差距会被放大。不过链式调用也有个很容易被忽略的坑不是所有方法都返回jQuery对象。比如.width()、.height()、.text()这些取值方法在传参时可能返回对象但不传参时返回的是数值或字符串继续往后链就会报错。我见过有人这么写var width $(.box).width().addClass(test); // 报错width()没传参时返回数字压根没有addClass方法。这点初学者尤其容易掉坑里记住一条原则赋值型方法可以链取值型方法不要链。2.3 操作DOM时的性能策略jQuery操作DOM很方便但方便不意味着可以随意挥霍。页面上的DOM节点一旦多了频繁的增删改会造成“重排”和“重绘”直接影响页面流畅度。jQuery场景下最典型的性能问题有两个问题一循环里逐个插入节点。// 低效写法 for (var i 0; i 1000; i) { $(#list).append(li i /li); }每执行一次append浏览器都会重新计算元素位置和样式1000次就是1000次重排。正确的做法是拼接字符串或数组一次性插入// 高效写法 var html ; for (var i 0; i 1000; i) { html li i /li; } $(#list).append(html);问题二频繁读取导致布局抖动。比如循环里每次都读.width()或.offset()这些属性不是缓存的每次读取都会触发浏览器重新计算布局。如果你确实要读多次先在循环外存到变量里var listWidth $(#list).width(); for (var i 0; i 100; i) { // 使用listWidth而不是每次都调用$(#list).width() }这可能听起来像优化其实更像基本功。我排查过不少老项目的性能问题很大一部分不在数据量而在于DOM操作写得太随意。3. 事件机制深度解构——绑定、委托与动态元素3.1 事件绑定和事件委托到底差在哪jQuery最常用的.bind()和.on()表面看都是绑定事件但内部逻辑有本质区别。.bind()是直接给当前匹配的元素逐个绑定监听器元素后来才出现的话监听器不会生效。.on()则可以传入第二个参数selector实现事件委托——事件绑定在父级元素上由冒泡机制捕获子元素触发的事件。// 直接绑定未来新增的 .btn 点不动 $(.btn).on(click, function() { console.log(clicked); }); // 事件委托未来新增的 .btn 也能响应 $(#container).on(click, .btn, function() { console.log(clicked); });为什么事件委托在动态页面里极其重要因为前端开发中请求接口、渲染列表是常态Ajax拿到数据后往页面上插节点如果用直接绑定每次插入完都得重新绑定一次麻烦且容易漏。用委托则一劳永逸父容器只要存在无论子元素什么时候出现都能触发。事件委托还有一个隐性的性能优势如果你要给一个表格里的500行绑定点击事件直接绑定的方式是创建500个监听器委托方式只给表格本身创建1个监听器内存占用天差地别。行动态列表多的页面这个优化非常明显。3.2 事件命名空间与处理函数解绑jQuery事件系统里有个冷门但实用的特性——命名空间。它能在解绑事件时只解绑指定类型不影响其它绑定在同一个元素上的事件// 带命名空间的绑定 $(#element).on(click.custom, function() { console.log(custom click); }); // 只解绑custom命名空间的click事件 $(#element).off(click.custom);场景举一个你在组件初始化时绑定了滚动事件组件销毁时需要解绑但同一个元素可能还有其它逻辑绑定的scroll事件用.off(scroll)会把别人的也解除。带上命名空间就能做到精准拆除。jQuery 3.x之后.bind()、.delegate()这些旧方法被弱化推荐统一用.on()和.off()配合命名空间代码可控性强很多。3.3 滚动到底部加载更多的完整实现“jQuery滚动到底部加载更多”是个高频搜索词因为很多后台列表、移动端页面还在用这种传统方案。我给出一个经历过真实项目检验的写法$(window).on(scroll.pagination, function() { var scrollTop $(window).scrollTop(); var docHeight $(document).height(); var winHeight $(window).height(); // 距底部小于100px时触发 if (docHeight - (scrollTop winHeight) 100) { if (!window.isLoading) { window.isLoading true; loadMoreData(); } } }); function loadMoreData() { $.ajax({ url: /api/list, method: GET, data: { page: window.currentPage 1 }, success: function(res) { if (res.data.length 0) { window.currentPage; $(#list).append(res.data.map(function(item) { return div classitem item.name /div; }).join()); } else { // 没有更多数据解绑滚动监听防止无效请求 $(window).off(scroll.pagination); } window.isLoading false; }, error: function() { window.isLoading false; } }); }这里有几个关键点**加载锁isLoading**是必须的。滚动事件触发极其频繁如果没有锁一次滚动可能发出几十个相同请求。用全局变量做锁请求结束再解锁这是最朴素但最有效的防重方案。解绑监听也很关键。当接口返回没有更多数据时立即off掉滚动事件否则用户每次滚到底部都会发无意义的请求白耗资源。底部判断逻辑docHeight - (scrollTop winHeight)算的是当前视口底部距文档底部的距离小于100就触发预加载。这个阈值可以根据页面高度调整移动端设为50或80更灵敏桌面端设100比较稳妥。4. Ajax实战——Content-Type、请求配置与前后端数据对接4.1 $.ajax、$.get、$.post怎么选jQuery里发请求有三种常见方式$.get()、$.post()、$.ajax()。这三者的关系是前两个是$.ajax()的语法糖封装了预设的请求类型。如果只是简单获取数据、提交表单用$.get()或$.post()完全够。但一旦涉及请求头设置、超时控制、contentType修改、进度回调就必须回归$.ajax()。我平时定的标准是简单读数据用$.get()简单提交用$.post()什么复杂需求直接写一个$.ajax()。团队协作时尽量统一使用$.ajax()加配置对象的形式可读性和可维护性都更好因为所有配置一目了然。4.2 Content-Type前后端联调最容易翻车的设置“jQuery content type怎么设置”在热搜里排得很靠前说明很多人被坑过。contentType是发送请求时告诉服务器“我这次请求体是什么格式”的字段。常见有三种application/x-www-form-urlencodedjQuery的默认方式数据会被序列化成key1value1key2value2。适合普通表单提交。application/json请求体是JSON字符串。后端用Spring Boot这类框架时需要在方法参数上加RequestBody才能接收。multipart/form-data用于上传文件jQuery里通常不直接设置而是用FormData对象。最经典的坑就是后端接口期望RequestBody接JSON前端却用默认的form-urlencoded方式提交于是后端收到的name字段是null前端一脸懵。正确的JSON提交姿势$.ajax({ url: /api/user/save, method: POST, contentType: application/json; charsetutf-8, data: JSON.stringify({ name: 张三, age: 28 }), success: function(res) { console.log(res); } });注意两点contentType要显式指定为JSONdata必须是JSON.stringify()之后的字符串不能直接传对象。有的同学写了contentType: application/json但忘了stringifyjQuery会尝试把对象序列化成[object Object]后端解析直接报错。反过来后端要的是普通表单格式前端却传了JSON同样会出问题。每次联调出现参数接收异常先检查contentType和后端的Consumes或RequestBody是否匹配这个排查思路能解决80%的传参问题。4.3 FormData与文件上传的常见写法文件上传是后台系统里的高频需求。用jQuery加上FormData不需要设置contentType因为浏览器会自动加上multipart/form-data边界标记手动设置反而容易出错var formData new FormData(); formData.append(file, $(#fileInput)[0].files[0]); formData.append(remark, 年度报表); $.ajax({ url: /api/upload, method: POST, data: formData, contentType: false, processData: false, success: function(res) { console.log(上传成功, res); }, error: function(xhr, status, error) { console.log(上传失败, error); } });这里一定记得设置processData: false。jQuery默认会把传入的data对象转换成查询字符串对FormData来说这会直接破坏二进制数据。contentType: false是让jQuery别自作主张帮你设请求头交给浏览器自己处理。这两个设置缺一不可是文件上传能成功的前提。我看过有些人用$.ajax模拟进度条但jQuery本身对上传进度的支持比较弱一般是自己加XMLHttpRequest的upload.onprogress回调var xhr new XMLHttpRequest(); // 可以替换$.ajax里的xhr选项 $.ajax({ url: /api/upload, method: POST, data: formData, contentType: false, processData: false, xhr: function() { var newXhr new XMLHttpRequest(); newXhr.upload.addEventListener(progress, function(e) { if (e.lengthComputable) { var percentComplete Math.round((e.loaded / e.total) * 100); $(#progressBar).css(width, percentComplete %); } }); return newXhr; }, success: function(res) { console.log(done); } });这个技巧在做大文件上传的场景里很实用。前端监控上传百分比配合后端分片接收可以让用户的等待变得可预期体验感提升不少。4.4 SignalR、WebSocket场景下jQuery的位置很多人在搜“signalr前端应该怎么获取数据”和“前端websocket怎么用”。如果你在一个老项目里通过jQuery做Ajax请求同时又要接入SignalR或WebSocket做实时推送要注意的是它们和jQuery是互补关系不是替代关系。jQuery负责常规请求SignalR/WebSocket负责服务器主动推消息。SignalR生成的客户端代理在较新版本中已经不再强依赖jQuery但项目里如果因为旧代码引用了jQuery也不冲突。实际操作时只需要在SignalR的回调函数里封装jQuery的DOM更新逻辑不要混着写维护时边界会清晰很多。5. 性能优化与问题排查——从“能跑”到“跑得好”5.1 前端内存泄漏的典型排查路径“前端内存泄漏怎么排查”也是热搜里一个很实在的问题。jQuery时代的泄漏经常发生在以下几个地方第一事件监听器未解绑。比如一个弹窗组件每次打开都执行一次$(#btn).on(click, handler)关闭时却只隐藏了弹窗没有off。反复开关十几次后同一个按钮上绑了十几个handler页面就越来越慢。排查方法是在Chrome DevTools的Elements面板选中该元素在Event Listeners里看绑定数量。第二全局变量或闭包误引用。比如在某个回调里把DOM元素赋值给了全局变量window.temp $(#bigModal);这个temp会一直在内存里即使你把它从页面上移除了它的引用依然存在内存无法回收。必要时用完后delete或赋null。第三定时器未清理。页面里开了setInterval轮询接口离开页面时没有clearInterval定时器持续运行。如果你在定时器回调里操作了DOM还会导致DOM也被长期占用。排查时可以浏览器控制台输入setInterval相关的断点或者在组件销毁生命周期里统一清理。常用的排查工具就是Chrome DevTools的Memory面板做堆快照操作前拍一张操作后拍一张对比对象数量和保留路径定位被意外保留的jQuery对象或DOM节点。这个技能在面试里也比较加分因为它体现的不只是会写API而是对运行时机制有认知。5.2 选择器性能对比与优化jQuery选择器不只是$()一种不同写法的查找效率相差很大。按经验排个序$(#id)最快直接映射到原生getElementById$(tag)次之原生getElementsByTagName$(.class)依赖浏览器getElementsByClassName等一般也还行$(.parent .child)后代选择器需要遍历$(.parent .child)子选择器比后代选择器稍快$(li:first)$(li:even)这些伪类选择器通常最慢因为要遍历匹配集合再做过滤在实际项目里如果你发现某个页面操作卡顿可以从选择器入手做优化。一个很实用的改进是缓存jQuery对象尤其是在事件回调和循环里// 坏习惯每次使用都查一遍 $(.menu li).click(function() { $(.menu li).removeClass(selected); // 又查了一遍 $(this).addClass(selected); }); // 好习惯把对象缓存起来 var $menuItems $(.menu li); $menuItems.click(function() { $menuItems.removeClass(selected); $(this).addClass(selected); });缓存jQuery对象不仅能减少DOM查找开销还能让代码更清晰。在同一个作用域内如果多次用到同一个选择结果务必先存变量。5.3 jQuery与Vue、React共存的现实方案老项目改造时会遇到一个尴尬局面页面既用了jQuery又逐步引入了Vue或React。我见过最混乱的写法是用Vue管理数据然后又在Vue的mounted或destroyed里用jQuery手动操作DOM两者互相打架节点被Vue重新渲染后jQuery绑定的事件就丢了。如果短时间内无法彻底迁移比较推荐的做法是“分区隔离”用jQuery负责的部分集中在独立容器里Vue/React负责它的独立根节点两边通过自定义事件或全局事件总线通信。切忌在同一个组件里同时用两套方案操作同一块DOM。另一种相对平滑的方式是先把jQuery操作封装成纯函数比如initPagination(container, config)、renderTable(data, target)然后在框架生命周期里调用方便后续逐步替换成框架组件。日常开发中还有个小技巧用$.noConflict()释放$变量让jQuery和框架共处。具体用法是var jq $.noConflict()之后用jq(...)代替$(...)。如果页面上还引用了其它依赖$的库这个函数能有效避免冲突。5.4 页面初始化的时机选择很多刚学前端的人分不清$(document).ready()和window.onload的区别。ready()是在DOM结构加载完成后就执行不用等图片、样式表、iframe等外部资源全部加载完window.onload则要等所有资源加载完。绝大多数情况下操作DOM用ready()就够了而且它的执行时机明显更早用户感知页面“可用”的时间会更短。jQuery 3.0之后$(document).ready()的推荐写法是简化的$(function() {})你也可以直接用$(handler)。注意一点如果脚本是放在body末尾加载的DOM此时已经基本解析完ready不ready影响不大但如果脚本放在head里或者用defer、async加载ready机制就能帮你避免undefined操作的报错。6. 从jQuery走向进阶——它教给你的远不止API6.1 用jQuery理解原生JavaScript的底层逻辑jQuery的源码是很多前端开发者“顿悟”的起点。比如你写过$(#id)之后再去看浏览器原生的querySelector和getElementById的差异就会更清晰用过.on()之后再看原生addEventListener和removeEventListener理解事件冒泡和捕获就更容易。框架带给你的可能是“工程化能力”但jQuery带给你的更像“浏览器操作基本功”。面试中经常出现的“前端八股文”里关于事件循环、DOM渲染、防抖节流、闭包等知识点都可以在jQuery的使用场景中找到对应案例。比如滚动加载更多就需要权衡节流和防抖事件委托中e.target的使用就是考察原生事件对象和冒泡机制的绝佳场景。6.2 老项目的jQuery维护规范建议如果你要接手一个jQuery老项目建议先做这几件事明确jQuery版本去官网看有没有已知安全问题老项目常见的是jQuery 1.x/2.x升级到3.x时要注意.on()、.remove()等行为变化全局搜索$(document).ready、.bind()、.live()这些旧写法逐步替换为.on()/.off()给项目建立统一的Ajax入口封装把接口地址和请求错误处理集中管理避免到处裸写$.ajax把公共DOM操作抽成函数或组件减少重复代码很多同学一听说要维护老项目就头大但从职业发展角度看能在混乱的大泥球里理清头绪、逐步优化这个能力本身就很有含金量。前端不是只有新框架才叫技术能把“旧而不死”的体系维护好同样体现功力。6.3 给初学者的学习路径建议想认真学会jQuery而不是“好像看懂了”可以按这个顺序练初学阶段完成一个TODO List利用选择器、DOM操作、事件绑定把增删改查全部走一遍。进阶阶段写一个Ajax分页列表必须包含加载状态、空数据状态、错误状态。综合阶段写一个图片上传加预览的功能用FormData处理输入校验和进度展示。阅读阶段打开jQuery源码中init和on的实现不求全懂只看思路。迁移阶段把一个用jQuery写的模块改成原生JavaScript或Vue体会两边的差异这能帮你把“jQuery思维”顺利过渡到“现代前端思维”。我当年就是这么练的印象最深的是第三步因为涉及FormData、contentType、xhr自定义等一堆细节调试到凌晨才跑通。但打通的那一瞬间对浏览器HTTP请求的理解就一下清晰了。这类经验其实是框架卷不走的因为它是Web的底层知识今天你用fetch发FormData底层逻辑和当年jQuery封装的还是一模一样。从整体来看jQuery给我最大的启发是好工具不是让你永远依赖它而是让你在用它解决问题的过程中理解问题本身。等到你哪天发现原生API已经足够顺滑、不再需要jQuery时说明你已经真的成长了而不是“抛弃了过时的东西”那么简单。

最新新闻

日新闻

周新闻

月新闻