jQuery 通过简化 DOM、事件和 AJAX 操作让 JavaScript 更易用。了解它是什么、为何衰落,以及今天在何种情况下仍然有意义。

jQuery 是一个小型的 JavaScript 库,它让网页上的常见任务更容易——比如选择元素、响应点击、修改文本、显示/隐藏页面部分,以及向服务器发送请求。
如果你曾见过像 $("button").click(...) 这样的代码,那就是 jQuery。$ 只是“在页面上查找某个东西并对它做点事”的快捷方式。
本指南偏实用、少技术细节:解释 jQuery 是什么、它为何曾流行、为什么新项目不常使用它,以及如果你的网站还在用它时该怎么处理。文章故意写得较长,以便包含清晰示例和现实可行的建议,而不是匆匆结论。
当人们说 jQuery 被“遗忘”时,他们通常不是指它消失了,而是意味着:
所以故事并不是“jQuery 死了”。更准确的说法是:jQuery 从前端工作的默认工具,变成了你可能继承的遗留依赖——偶尔也会被有意选择。
在 jQuery 出现之前,前端工作经常意味着反复编写那些小而恼人的代码片段——然后在多个浏览器中测试并发现它们表现不同。即便像“找到这个元素”、“绑定点击处理”或“发送请求”这样的简单目标,也可能变成一堆兼容性分支。
许多早期的 JavaScript 工作更多是在与环境搏斗。你可能写出在某个浏览器上工作的代码,然后再加上额外分支让它在另一个浏览器上也能跑通。团队会维护自己的“迷你库”来应对日常的 UI 变更。
结果是:开发变慢、Bug 增多,而且总担心一个小改动会破坏仍被用户依赖的旧浏览器。
浏览器在重要细节上不一致。DOM 选择方法、事件处理,甚至获取元素尺寸的方式都可能不同。尤其是 Internet Explorer,在事件和 XMLHTTP 请求上有不同的 API,所以“标准”代码并不总是能跨浏览器通用。
这很关键,因为网站不是只为一种浏览器构建的。如果你的结账表单、导航菜单或模态对话框在主流浏览器中失效,那就是一个真实的业务问题。
jQuery 之所以重要,是因为它提供了一个一致且友好的 API,弥补了这些差异。
它让常见任务变得极其简单:
更重要的是,jQuery 的“少写、多做”风格让团队更快交付,并减少了浏览器特定的意外——尤其是在“现代 DOM API”还不够强大或广泛支持的时代。
jQuery 的真正优势并不是引入了全新的概念——而是让常见的浏览器任务在不同浏览器之间表现一致且易用。如果你在读旧的前端代码,通常会看到 jQuery 用于四类日常工作。
$ 函数的思想)$() 函数允许你使用类 CSS 的选择器“抓取”元素,然后把它们作为一个集合来操作。
你不需要处理浏览器的怪异行为或冗长的 API,而是可以通过简短、可链式的调用选择所有条目、查找子元素或向上查找父元素。
jQuery 让响应用户操作变得简单:
click 处理按钮和链接submit 处理表单ready 在页面加载完后运行代码它还平滑处理了浏览器对事件对象和绑定方式的差异,这在浏览器支持不均衡时非常重要。
在 fetch() 成为标准之前,jQuery 的 $.ajax()、$.get() 和 $.post() 是一个简单明了的方式,用于向服务器请求数据并在不刷新页面的情况下更新页面。
这推动了现在看起来很普通的模式——实时搜索、“加载更多”按钮、局部页面更新——使用一个熟悉的 API 即可实现。
jQuery 推广了常见的 UI 小技巧,例如 hide()、show()、fadeIn()、slideToggle() 和 animate()。这些在菜单、通知和基础过渡中非常方便——尤其在 CSS 支持还不稳定的时代。
综合起来,这些便利解释了为什么遗留 JavaScript 代码中常常以 $( 开头,以及为什么 jQuery 曾长期是默认工具。
jQuery 的一个名声来源于完成常见 UI 任务时所需代码的简洁性——尤其是在浏览器差异令人头疼的时期。下面的并列示例更易于比较。
jQuery
// Select a button and run code when it's clicked
$('#save').on('click', function (e) {
e.preventDefault();
$('.status').text('Saved!');
});
现代(原生)JavaScript
// Select a button and run code when it's clicked
const saveButton = document.querySelector('#save');
const status = document.querySelector('.status');
saveButton?.addEventListener('click', (e) => {
e.preventDefault();
if (status) status.textContent = 'Saved!';
});
乍一看,jQuery 版本显得“更干净”:一条链式调用选择元素、附加处理器并更新文本。简洁性曾是其重要卖点。
现代 JavaScript 略显冗长,但也更明确:
querySelector 和 addEventListener 明确说明了在做什么。textContent 是标准 DOM 属性(没有库的封装)。?.)和空值检查让在元素不存在时的行为更清晰。取决于上下文。如果你维护一个到处都在用 jQuery 的旧代码库,jQuery 片段可能更一致、更快上手。如果你写新代码,现代 DOM API 已被广泛支持、能减少依赖,并更易与当今的工具链和框架集成。
长期以来,jQuery 最大的优势是可预测性。你可以用统一方式选择元素、绑定事件或发起 Ajax 请求——而且在大多数环境下都能工作。
随着时间推移,浏览器标准化并改进。许多 jQuery 打包的“必需便利”现在已内置到 JavaScript 中,因此为了完成基础工作,你通常不再需要额外库。
现代 DOM 方法覆盖了许多常见的 jQuery 模式:
document.querySelector() / document.querySelectorAll() 在很多场景替代 $(...)。element.classList.add() / .remove() / .toggle() 可做类操作。element.addEventListener() 在大多数用例中替代了 jQuery 的事件封装。你可以依赖标准 API,在现代浏览器中得到一致表现,而无需记住 jQuery 专有的辅助方法。
曾经 $.ajax() 是常用选项,而现在 fetch() 与 JSON 配合能处理许多日常请求:
const res = await fetch('/api/items');
const data = await res.json();
你依然需要显式处理错误和超时,但核心思路——无需插件即可发起请求——现在已成为内置能力。
jQuery 通过回调和 $.Deferred 把许多人带入了异步编程的世界。如今,Promises 与 async/await 让异步流程更易读,ES 模块也让代码组织更清晰。
现代 DOM API + fetch + 现代语言特性这几者的组合,已经消除了团队默认使用 jQuery 的许多原始理由。
jQuery 诞生于“多页网站”时代:服务器渲染 HTML,浏览器加载页面,你在现有标记上“撒上一些行为”——点击处理、动画、Ajax 调用等。
现代前端框架则颠覆了这种模式。应用通常在浏览器中生成大部分 UI,并保持与数据的同步。
React、Vue 和 Angular 将组件化思路普及开来:把界面拆成小的、可复用的部分,每个部分拥有自己的标记、行为和状态。
在这种模式下,框架往往成为屏幕上内容的“单一事实源”。它跟踪状态、在状态变更时重新渲染 UI,并期望你以声明式方式描述视图(“当 X 为真时显示 Y”)。
而 jQuery 倾向于命令式的 DOM 操作(“找到这个元素,改它的文本,隐藏它”)。这往往与框架的渲染周期冲突:如果你在组件“控制”的 DOM 节点上手动修改,下一次重渲染可能覆盖你的改动,或导致难以调试的不一致。
随着 SPA 的流行,团队采用了构建工具和打包器(如 Webpack、Rollup、Vite)。你不再只是把几个 script 标签丢进页面,而是按需导入模块、打包使用到的代码并做性能优化。
这种转变也让团队更关注依赖体积。仅仅为了“以防万一”把 jQuery 拉进来变得不再自然,尤其当每一千字节和第三方更新都可能影响构建时。
你当然可以在框架内使用 jQuery,但它通常变成一个特殊孤岛——更难测试、更难推理,也更容易在重构时出问题。因此许多团队选择使用框架原生的模式替代 jQuery 风格的 DOM 脚本。
jQuery 本身并不算“巨量”,但它往往伴随其他包袱出现。很多依赖 jQuery 的项目还会积累插件(滑块、日期选择器、灯箱、校验器),每个插件都会增加更多第三方代码需要下载和解析。久而久之,一个页面可能会加载多个重复或重叠的工具——尤其是当功能快速添加但从未回顾时。
更多的 JavaScript 意味着浏览器需要更多时间去获取、解析和执行代码,才能让页面可用。这个影响在移动设备、慢速网络和老旧硬件上尤为明显。即便用户最后得到流畅体验,“可用时间”也可能因额外脚本和依赖而变长。
在长期运行的网站中,常见模式是“混合”代码库:一些功能用 jQuery 写,较新的部分用框架(React、Vue、Angular),还夹杂着一些原生 JS 片段。这种混合会令人困惑:
当多种风格共存时,小改动变得更有风险。开发者更新了一个组件,但旧的 jQuery 脚本仍然访问相同的标记并修改它,导致难以复现的 Bug。
团队逐步远离 jQuery 并不是因为它“不能工作”,而是因为现代项目更注重减小包体积与明确 UI 行为的归属。随着站点规模的增长,减少第三方代码和统一方法通常会让性能调优、调试和新人入职更简单。
jQuery 不只是流行——它一度成为默认。多年间,它是让交互页面在浏览器间都能可靠工作的最简单方式,因此它被广泛嵌入到各种模板、片段、教程和复制粘贴的解决方案中。
一旦这样做了,jQuery 就难以避免:即使某个站点只用到一个小功能,它也常常加载整个库,因为其他代码都假定它存在。
一个重要原因是 jQuery 的成功让它在第三方代码中“无处不在”。许多旧的 UI 小部件、滑块、灯箱、表单验证以及主题脚本都以 jQuery 插件形式存在。如果站点依赖这些组件,移除 jQuery 意味着要重写或替换它们,而不是只改几行代码。
WordPress 是“遗留 jQuery”的一个大来源。许多主题和插件(尤其是多年前创建的)使用 jQuery 来实现前端行为,历史上 WordPress 后台页面也常依赖它。即便新版逐步转向现代 JS,长期存在的大量扩展仍使得 jQuery 在许多安装中无法轻易去除。
旧站点通常优先考虑“别破坏现有功能”。保留 jQuery 在以下情况下往往是最安全的选择:
总之,jQuery 并不总是“被遗忘”,它常常是构建网站时奠定的基础,而基础通常不会轻易更换。
jQuery 并不是“糟糕”软件——只是相比过去它不再那么必需。仍有一些现实场景下,保留或新增少量 jQuery 是最实用的选择,特别是当你以时间、兼容性或稳定性为优先而非架构纯净时。
如果项目需要包含旧浏览器(尤其是旧版 Internet Explorer),jQuery 在 DOM 选择、事件处理和 AJAX 上仍能以更少的 polyfill 简化工作。在这种情况下,你本来就需要额外代码支持兼容性,把 jQuery 作为兼容包的一部分通常是可以接受的。
如果站点已经围绕 jQuery 构建,采用相同风格去做小 UI 改动通常更快、更安全。混合不同方法会带来困惑(两种事件绑定方式、两种 DOM 操作方式),使维护更困难。
一个合理的规则是:如果你只修改一两个页面且应用总体稳定,使用 jQuery 修补是可以的——只是要避免把 jQuery 用进新的“系统”,日后又不得不撤回。
对于没有构建流程的简单营销页面或内部工具,jQuery 仍然是个方便的“单个 script 标签”辅助工具。当你只想实现几个交互(切换菜单、简单表单行为)而不想引入构建管道时,它很实用。
许多成熟插件(日期选择器、表格、灯箱)都是基于 jQuery 构建的。如果某个旧插件对业务关键且稳定,保留 jQuery 作为依赖可能是风险最低的方案。
在做决定前,检查是否存在维护良好的非 jQuery 替代品,或是升级插件是否会引发无法承受的全面重构。
摆脱 jQuery 更像是逐步减少依赖而非一次性大改。最安全的方式是渐进式:在不破坏现有行为的前提下替换底层实现。
先回答三个实际问题:
这个审计能帮你避免替换不必要的部分,并发现像插件悄悄调用 $.ajax() 这样“隐藏”的依赖。
多数团队可以通过替换最常见的模式快速取得成效:
$(".card") → document.querySelectorAll(".card").addClass() / .removeClass() → classList.add() / classList.remove().on("click", ...) → addEventListener("click", ...)把改动拆成小的 PR,便于审查与回滚。
如果你用到 $.ajax(),把这些调用逐个端点迁移到 fetch()(或自建的 HTTP 帮助器)。保持响应格式相同,这样其余 UI 不需要立刻改动。
// jQuery
$.ajax({ url: "/api/items", method: "GET" }).done(renderItems);
// 现代 JS
fetch("/api/items")
.then(r => r.json())
.then(renderItems);
在移除 jQuery 前,为关键用户流程、表单提交和动态 UI 增加覆盖。即使是轻量的检查(Cypress 烟雾测试或 QA 清单)也能早期发现回归。尽量把变更放在功能开关后面发布,观察分析与错误率是否稳定。
如果想在重构时多一层保障,可以使用支持快照与回滚的工具进行迭代。例如,有些团队在现代化遗留前端时,会先在原型环境中试验替换方案,利用快照/回滚工作流在不丢失“已知良好”版本的前提下快速迭代。
如果你需要帮助组织整体计划,可以参阅 /blog/jquery-vs-vanilla-js,那里有可用于重构对比的基线示例。
从 jQuery 迁移通常不像“单纯替换语法”那么简单,而是要解开多年累积的假设。下面是常拖慢进度的陷阱与规避方法。
全面重写听起来干净利落,但常常会导致长期分支、众多回归和未完成功能的交付压力。更安全的策略是逐步替换:每次替换一个功能或页面,保持行为一致,并为变更部分添加测试。
如果在 jQuery 仍直接修改同一 DOM 节点的情况下引入 React/Vue/Svelte(或轻量组件系统),会出现“界面拉扯战”:框架重渲染会覆盖 jQuery 的修改,而 jQuery 又会改写框架认为自己控制的元素。
经验法则:划清边界。要么:
很多旧代码依赖委托事件,比如:
$(document).on('click', '.btn', handler)
原生 DOM 可以实现同样效果,但匹配逻辑以及 this/event.target 的期望可能不同。常见错误包括处理器在错误元素触发(因为嵌套的图标/span),或对动态新增元素不起作用(监听器附到错误的祖先)。在替换委托事件时请确认:
closest())jQuery UI 的效果和自定义动画有时会无意间掩盖无障碍问题——或引入新的问题。替换淡入/滑动/切换行为时,重新检查:
aria-expanded)prefers-reduced-motion)早期捕获这些问题会加快迁移速度,并让 UI 更可靠——即便最后一个 $() 还没被移除。
jQuery 不是“糟糕”的工具。它解决了真实的问题——尤其是在浏览器行为不一致且实现交互页面需要大量重复 DOM 代码的时代。变化在于:对于新项目,你通常不再需要它。
推动它由“默认选择”变成“遗留依赖”的力量包括:
如果你维护旧站点,jQuery 仍可能是合理工具——尤其适合小修复、稳定插件或不值得重构的页面。如果你在开发新功能,优先考虑原生 JavaScript,并仅在明确节省时间或成本时保留 jQuery。
继续学习时可参考:
如果你想更快地现代化,可以考虑帮助你增量原型和发布的工具。比如一些平台允许你在对话中描述行为,生成基于 React 的 UI 和所需的后端,并在准备好后导出源码以便与现有代码库集成。
如果你在评估工具或支持选项,也可以查看 /pricing 了解更多信息。
jQuery 是一个 JavaScript 库,简化了常见的浏览器任务,比如选择元素、处理事件、发起 Ajax 请求,以及做一些基本的效果(显示/隐藏、淡入/淡出、滑动)。它的标志性用法是使用 $() 函数来查找元素并链式调用方法。
$ 只是一个快捷函数(通常由 jQuery 提供),用于在页面中查找元素——类似于 document.querySelectorAll()——并返回一个可以链式调用方法的 jQuery 对象。
如果在旧代码中看到 $(),通常意味着“选中某个元素,然后对它做点事情”。
它受欢迎的原因在于将不一致的浏览器行为变得一致。在早期,像事件、DOM 遍历和 Ajax 这样的简单操作常常需要针对不同浏览器写特殊处理。
jQuery 提供了一个可预期的 API,让团队可以更快地交付功能,减少跨浏览器的意外问题。
主要是因为现代浏览器和 JavaScript 语言已经追上了 jQuery 的功能。今天你通常可以用内置功能替代经典的 jQuery 操作:
querySelector / querySelectorAll 做选择不是的。许多现有网站仍然在使用 jQuery,并且它仍然可用。所谓“遗留”通常意味着它在旧代码库中更常见,而不是新项目中常见。
更实际的问题是基于性能、维护成本和依赖(特别是插件)来判断是否继续保留它。
因为它深植于旧生态系统,尤其是主题和插件中。一个常见例子是 WordPress:许多扩展历史上都假定页面存在 jQuery。
如果你的网站依赖某个只能用 jQuery 的插件(滑块、日期选择器、灯箱、校验插件),移除 jQuery 往往意味着要替换该插件,而不只是改几行代码。
在少数实际场景下,保留或加入少量 jQuery 仍然是合理的选择:
在这些情况下,稳定性和速度可能比减少依赖更重要。
逐步、可测地进行迁移:
$.ajax() 逐个端点迁移到 fetch()(或小型 HTTP 帮助器)。事件委托是常见问题之一。像下面这样的 jQuery 代码:
$(document).on('click', '.btn', handler)
在原生 DOM 中可以实现相同功能,但匹配逻辑以及 this / event.target 的预期可能不同。替换委托事件时通常需要:
是的——效果和 DOM 重写可能无意中破坏无障碍体验。替换 hide() / show() 或滑动/淡入效果时,请重新检查:
aria-expandedprefers-reduced-motion)保持行为一致不仅仅是视觉,还包括交互和键盘流程。
classListaddEventListener 处理事件fetch + async/await 发请求因此新项目不再常常需要一个兼容层来处理这些基础功能。
小的 PR 与分阶段发布能降低回归风险。
event.target.closest('.btn') 来确认触发元素请测试动态加载的内容(页面加载后新增的元素)。