You-Dont-Need-jQuery:用原生 JavaScript 替代 jQuery 的完整实践指南(Query、DOM、Ajax、Events、Utilities)

发布时间:2026/10/1 16:55:09
You-Dont-Need-jQuery:用原生 JavaScript 替代 jQuery 的完整实践指南(Query、DOM、Ajax、Events、Utilities) 教程前端【免费下载链接】You-Dont-Need-jQueryExamples of how to do query, style, dom, ajax, event etc like jQuery with plain javascript.项目地址https://gitcode.com/gh_mirrors/yo/You-Dont-Need-jQuery点击查看免费下载本指南以仓库 You-Dont-Need-jQuery 的印尼语版 README-id.md 为核心脉络系统梳理如何用浏览器原生NativeAPI 替代 jQuery 中查询元素、操作样式、操纵 DOM、发送 Ajax 请求、绑定事件与使用工具函数等高频方法。你将获得一套可直接复制运行、经过仓库测试用例验证的 jQuery → 原生 JavaScript 对照速查表并了解每种替代方案的边界与注意事项从而在现代化前端项目中逐步摆脱对 jQuery 的依赖。为什么还需要这份对照指南前端环境发展极快现代浏览器已经实现了足够生产可用的 DOM/BOM API。我们不再需要为了操作 DOM 或处理事件而从零学习 jQuery。与此同时React、Angular、Vue 等前端库的普及使得直接操作 DOM 逐渐成为一种反模式anti-patternjQuery 的使用价值因此进一步降低。本项目的价值在于汇总了 jQuery 常用方法在原生 JavaScript 中几乎一一对应的实现方式帮助你在仍需以原生方式操作 DOM的场景下快速迁移。需要特别说明的两点前提来自英文版 README.md 的 NoticejQuery 本身仍然是一个优秀的库在很多场景下依然有合理的用途如果不想迁移完全不必迁移。这些替代方案并非在所有场景下都与 jQuery 完全等价建议在使用前先进行测试验证。本仓库恰好为此提供了测试基础仓库基于 Vitest jsdom 搭建了与 jQuery 逐一对拍的测试套件见 vitest.config.js 与 test/ 目录后文每个章节都会给出对应的测试文件证据。如何运行仓库测试验证这些替代方案在动手迁移前可以先在本地跑通仓库自带的验证用例确认每个原生实现与 jQuery 行为一致git clone https://gitcode.com/gh_mirrors/yo/You-Dont-Need-jQuery cd You-Dont-Need-jQuery npm install npm testnpm test实际执行的是vitest run见 package.jsonnpm run tdd则进入监听模式持续测试。测试环境为 jsdomvitest.config.js因此 DOM、事件、动画相关的用例都可在 Node 环境稳定复现。开发依赖为jquery ^4.0.0、jsdom ^30.1.0、vitest ^5.0.1运行环境要求 Node^22.12.0 || 24.0.0package.json。Query Selector原生查询替代方案对于 class、id、attribute 等常见选择器可以用document.querySelector或document.querySelectorAll直接替代。二者差异如下document.querySelector返回第一个匹配的元素document.querySelectorAll返回所有匹配元素组成的静态 NodeList支持forEach也可以用Array.from(document.querySelectorAll(selector))转换为真正的数组当没有匹配元素时jQuery 返回一个空的 jQuery 对象、querySelectorAll返回空的 NodeList而document.querySelector返回null——请务必留意空指针Null Pointer问题。注意document.getElementById、document.getElementsByClassName、document.getElementsByTagName比querySelector*略快但getElementsBy*返回的是动态的liveHTMLCollection会随 DOM 变化而自动更新。除非你实测确认了性能瓶颈否则优先使用querySelector*。1.0 按选择器查询// jQuery $(selector); // Native document.querySelectorAll(selector);1.1 按 class 查询// jQuery $(.class); // Native document.querySelectorAll(.class); // 或 document.getElementsByClassName(class);1.2 按 id 查询// jQuery $(#id); // Native document.querySelector(#id); // 或 document.getElementById(id);1.3 按 attribute 查询// jQuery $(a[target_blank]); // Native document.querySelectorAll(a[target_blank]);1.4 在子节点中查找查找节点// jQuery $el.find(li); // Native el.querySelectorAll(li);获取 body// jQuery $(body); // Native document.body;获取 attribute// jQuery $el.attr(foo); // Native el.getAttribute(foo);获取 data attribute// jQuery $el.data(foo); // Native el.dataset.foo; // 或 el.getAttribute(data-foo);1.5 兄弟 / 前一个 / 后一个元素所有兄弟元素// jQuery $el.siblings(); // Native [...el.parentNode.children].filter((child) child ! el );前一个元素// jQuery $el.prev(); // Native el.previousElementSibling;后一个元素// jQuery $el.next(); // Native el.nextElementSibling;1.6 Closest向上查找最近的匹配祖先返回从当前元素开始、沿 DOM 树向上遍历时第一个匹配给定选择器的元素// jQuery $el.closest(selector); // Native el.closest(selector);1.7 Parents Until向上收集祖先直到匹配项获取每个匹配元素的祖先节点不包含由 selector、DOM 节点或 jQuery 对象匹配到的那个元素本身// jQuery $el.parentsUntil(selector, filter); // Native function parentsUntil(el, selector, filter) { const result []; // match start from parent el el.parentElement; while (el !el.matches(selector)) { if (!filter || el.matches(filter)) { result.push(el); } el el.parentElement; } return result; }1.8 表单相关读取 Input/Textarea 的值// jQuery $(#my-input).val(); // Native document.querySelector(#my-input).value;获取e.currentTarget在一组.radio中的索引// jQuery $(.radio).index(e.currentTarget); // Native [...document.querySelectorAll(.radio)].indexOf(e.currentTarget);1.9 Iframe 内容$(iframe).contents()对应原生contentDocument// jQuery $iframe.contents(); // Native iframe.contentDocument;在 iframe 内部查询// jQuery $iframe.contents().find(.css); // Native iframe.contentDocument.querySelectorAll(.css);测试佐证测试文件 test/query.spec.js 在 jsdom 中构造了嵌套ul/li结构逐一验证按 classL38-L45、按 idL47-L49、按 attributeL51-L59、子节点查询L61-L69等场景下原生查询结果与$查询结果完全一致同时验证了带过滤函数的 prevAll/nextAllL91-L117、:contains文本匹配L119-L130以及 parentsUntil 的 filter 参数行为L132-L163。CSS Style样式读写与尺寸计算2.1 CSS 读写与 class 操作读取样式注意返回的是已解析resolved后的值例如rgb(255, 0, 17)而非#f01// jQuery $el.css(color); // Native getComputedStyle(el).color;设置样式// jQuery $el.css({ color: #f01 }); // Native el.style.color #f01;批量设置多个样式// jQuery $el.css({ color: #f01, border-color: #f02 }); // Native Object.assign(el.style, { color: #f01, borderColor: #f02 });class 增删查切原生统一由classList提供// jQuery // Native $el.addClass(className); el.classList.add(className); $el.removeClass(className); el.classList.remove(className); $el.hasClass(className); el.classList.contains(className); $el.toggleClass(className); el.classList.toggle(className);2.2 宽度与高度width 与 height 理论上是同一套逻辑以 height 为例窗口高度两种口径注意滚动条是否计入// jQuery $(window).height(); // 不含滚动条行为与 jQuery 一致 window.document.documentElement.clientHeight; // 含滚动条 window.innerHeight;文档高度// jQuery $(document).height(); // Native const body document.body; const html document.documentElement; const height Math.max( body.offsetHeight, body.scrollHeight, html.clientHeight, html.offsetHeight, html.scrollHeight );元素高度jQuery 的.height()返回的是 content 区域高度需要手工扣除 padding 与 border// jQuery $el.height(); // Native function getHeight(el) { const styles window.getComputedStyle(el); const height el.offsetHeight; const borderTopWidth parseFloat(styles.borderTopWidth); const borderBottomWidth parseFloat(styles.borderBottomWidth); const paddingTop parseFloat(styles.paddingTop); const paddingBottom parseFloat(styles.paddingBottom); return height - borderBottomWidth - borderTopWidth - paddingTop - paddingBottom; } // 精确到整数border-box 时为 height - bordercontent-box 时为 height padding el.clientHeight; // 精确到小数border-box 时为 heightcontent-box 时为 height padding border el.getBoundingClientRect().height;2.3 位置与偏移相对于 offset parent 的位置// jQuery $el.position(); // Native const position { left: el.offsetLeft, top: el.offsetTop };相对于文档的偏移注意要叠加滚动量// jQuery $el.offset(); // Native function getOffset (el) { const box el.getBoundingClientRect(); return { top: box.top window.scrollY, left: box.left window.scrollX }; }2.4 滚动位置// jQuery $(window).scrollTop(); // Native window.scrollY;DOM Manipulation元素增删改查3.1 移除元素// jQuery $el.remove(); // Native el.remove();3.2 文本读写读取文本包含所有后代节点的合并文本// jQuery $el.text(); // Native el.textContent;设置文本// jQuery $el.text(string); // Native el.textContent string;3.3 HTML 读写// jQuery // Native $el.html(); el.innerHTML; $el.html(htmlString); el.innerHTML htmlString;3.4 Append追加到父元素末尾jQuery 对 DOMString 与 Node 对象使用统一语法而原生append存在一个关键差异字符串会被当作纯文本插入不会被解析为 HTML。因此// jQueryDOMString 与 Node 对象语法统一 $parent.append(newEl | div idcontainerHello World/div); // Native元素或文本字符串作为纯文本插入不解析为 HTML parent.append(newEl | Hello World); // NativeHTML 字符串 parent.insertAdjacentHTML(beforeend, div idcontainerHello World/div);3.5 Prepend插入到父元素开头// jQuery $parent.prepend(newEl | div idcontainerHello World/div); // Native元素或文本 parent.prepend(newEl | Hello World); // NativeHTML 字符串 parent.insertAdjacentHTML(afterbegin, div idcontainerHello World/div);3.6 insertBefore在选中元素前插入// jQuery $newEl.insertBefore(selector); const el document.querySelector(selector); // Native元素 el.before(newEl); // NativeHTML 字符串 el.insertAdjacentHTML(beforebegin, div idcontainerHello World/div);3.7 insertAfter在选中元素后插入// jQuery $newEl.insertAfter(selector); const el document.querySelector(selector); // Native元素 el.after(newEl); // NativeHTML 字符串 el.insertAdjacentHTML(afterend, div idcontainerHello World/div);测试佐证这些文本 vs HTML的差异已在 test/dom.spec.js 中被显式验证——append(b...)后最后一个子节点是TEXT_NODE而insertAdjacentHTML(beforeend, ...)后最后一个子节点是B元素L13-L27before/after插入顺序L47-L56、removeL41-L45同样有一一对应的断言。另外英文版 README.md 中还包括wrap、unwrap、replaceWith、cloneNode(true)深度克隆、el.replaceChildren()清空子节点、template解析 HTML 片段等更多 DOM 操作替代方案仓库测试 test/dom.spec.js 对其均做了与 jQuery 输出的逐字对拍需要时可进一步查阅。Ajax用 Fetch API 替代 XMLHttpRequest 与 $.ajaxFetch API 是 XMLHttpRequest 的标准替代品已可用于所有现代浏览器。与$.ajax的一个关键行为差异是fetch不会在收到 HTTP 错误状态如 404 或 500时 reject你需要自行检查response.ok。如果仍需要 JSONP可以尝试社区方案fetch-jsonp。4.0 请求 JSON 数据// jQuery $.getJSON(url).done(handleData).fail(handleError); // Native fetch(url) .then((response) { if (!response.ok) { throw new Error(HTTP ${response.status}); } return response.json(); }) .then(handleData) .catch(handleError);4.0.1 POST 提交 JSON 数据// jQuery $.ajax({ url, method: POST, contentType: application/json, data: JSON.stringify(data), }); // Native fetch(url, { method: POST, headers: { Content-Type: application/json }, body: JSON.stringify(data), });4.0.2 取消请求与超时取消abort// jQuery const jqXHR $.ajax({ url, timeout: 5000 }); jqXHR.abort(); // Native const controller new AbortController(); fetch(url, { signal: controller.signal }); controller.abort();超时利用AbortSignal.timeout2022 年的 API// Native (timeout) fetch(url, { signal: AbortSignal.timeout(5000) });4.1 加载 HTML 并注入匹配元素// jQuery $(selector).load(url, completeCallback) // Native fetch(url) .then((response) response.text()) .then((html) { document.querySelector(selector).innerHTML html; }) .then(completeCallback);测试佐证测试文件 test/ajax.spec.js 通过 stub 全局fetch验证了成功路径L21-L30与 404 路径L32-L41断言错误消息为HTTP 404并验证AbortController与AbortSignal.timeout(5000)的行为L43-L49。这印证了fetch 不因 HTTP 错误状态 reject、必须检查response.ok这一文档结论。Events事件绑定、委托与触发5.1 用 on 绑定事件// jQuery $el.on(eventName, eventHandler); // Native el.addEventListener(eventName, eventHandler);5.1.1 用 one 只绑定一次// jQuery $el.one(eventName, eventHandler); // Native el.addEventListener(eventName, eventHandler, { once: true });5.1.2 事件委托// jQuery $el.on(eventName, selector, eventHandler); // Native el.addEventListener(eventName, (event) { const target event.target.closest(selector); if (target el.contains(target)) { eventHandler.call(target, event); } });5.2 用 off 解绑事件// jQuery $el.off(eventName, eventHandler); // Native el.removeEventListener(eventName, eventHandler); // Native一次性移除多个监听器相当于 jQuery 的 namespace const controller new AbortController(); el.addEventListener(click, onClick, { signal: controller.signal }); el.addEventListener(keydown, onKeydown, { signal: controller.signal }); controller.abort();5.3 触发自定义事件jQuery 的trigger触发的事件会冒泡bubbling而原生事件默认不冒泡需要显式设置bubbles: true。事件数据通过event.detail传递// jQuery $(el).trigger(custom-event, {key1: data}); // Native const event new CustomEvent(custom-event, { bubbles: true, cancelable: true, detail: { key1: data }, }); el.dispatchEvent(event);测试佐证测试文件 test/events.spec.js 验证了{ once: true }下事件只触发一次L14-L22委托场景下只有真正命中li的点击才被处理、且回调中的this指向目标元素L24-L42AbortController.abort()后 click 与 focus 监听器均不再响应L44-L55CustomEvent的detail能被外层监听器完整收到L57-L72。Utilities常用工具函数6.1 isArray// jQuery $.isArray(array); // Native Array.isArray(array);6.2 Trim去除首尾空白// jQuery $.trim(string); // Native string.trim();6.3 对象合并Object Assign将两个或多个对象的内容合并到一个新对象不修改任何入参。与不带deep的$.extend相同Object.assign与 spread 都只做浅拷贝shallow copy// jQuery $.extend({}, object1, object2); // Native Object.assign({}, object1, object2); // Native (spread) ({ ...object1, ...object2 });单个对象的深拷贝// jQuery $.extend(true, {}, object); // Native。注意函数和 DOM 节点无法被 clone structuredClone(object);6.4 Contains判断是否包含// jQuery $.contains(el, child); // Native el ! child el.contains(child);测试佐证测试文件 test/utilities.spec.js 对上述工具做了与 jQuery 的逐项对拍Object.assign/spread 与$.extend结果一致、structuredClone与$.extend(true, ...)结果一致且嵌套对象不共享引用L70-L80isWindow的判定逻辑L82-L91inArray与indexOf/includes的等价性L6-L12isPlainObject对各种对象/类的判定L14-L33merge就地合并行为L35-L43parseHTML保留文本节点L45-L62以及元素是否存在的判断L64-L69。浏览器支持Browser yang DidukungChromeEdgeFirefoxSafariOperaLatest ✔Latest ✔Latest ✔Latest ✔Latest ✔本文档与仓库中的代码片段面向当前的 evergreen 浏览器Chrome、Edge、Firefox、Safari。Internet Explorer 已被微软停止支持因此仓库已移除所有针对 IE 的 fallback如果你仍需要 IE 兼容代码可回看仓库 git 历史中最后一个与 IE 兼容的版本对应提交c4e00b3。另外部分代码片段使用了较新的 APIPromise.withResolvers()2024、el.replaceChildren()2020与AbortSignal.timeout()2022。如果你仍需要支持更老的浏览器建议查阅 Web Platform Baseline 了解各特性的跨浏览器安全使用范围。语言版本与其他章节本指南对应的原文 README-id.md 只是该项目众多翻译版本之一英文原文 README.md 中还包括本文未展开的Promisesdone/fail/always→then/finally、$.when→Promise.all、$.Deferred→new Promise/Promise.withResolvers()与AnimationWeb Animations APIel.animate()实现 show/hide、fadeIn/fadeOut、slideUp/slideDown 等效果章节仓库中分别有 test/promises.spec.js 与 test/animation.spec.js 提供验证。其他语言版本包括 简体中文、正體中文、한국어、日本語、Português(PT-BR) 等可在仓库根目录找到。结语从$()到querySelectorAll、从$.ajax到fetch、从$el.on到addEventListener现代浏览器已经为几乎所有高频 jQuery 操作提供了原生替代。迁移的关键在于理解每一对 API 的行为差异——例如 fetch 不拒绝 HTTP 错误状态、原生append不解析 HTML 字符串、querySelector无匹配时返回null、原生事件默认不冒泡等。本文所有结论均由仓库内测试用例 test/ 与 jQuery 4.x 直接对拍验证你可以通过npm install npm test在本地复现。本仓库遵循 MIT 协议见 LICENSE可自由参考与使用。赞分享教程前端【免费下载链接】You-Dont-Need-jQueryExamples of how to do query, style, dom, ajax, event etc like jQuery with plain javascript.项目地址https://gitcode.com/gh_mirrors/yo/You-Dont-Need-jQuery点击查看免费下载相关推荐BabelDOC公式版式原样保留的免费 PDF 翻译工具写给经常啃论文的科研人员BabelDOC公式版式原样保留的免费 PDF 翻译工具写给经常啃论文的科研人员 刚把一份 30 页的英文 PDF 翻译完公式变乱码、双栏排版全乱、表格结教程前端You-Dont-Need-jQuery: 纯 JavaScript 替代 jQuery 的实践指南You Dont Need jQuery : 纯 JavaScript 替代 jQuery 的实践指南 项目介绍 在现代浏览器环境中原生JavaScript已教程前端You-Dont-Need-jQuery现代JavaScript替代jQuery的完整指南You Dont Need jQuery现代JavaScript替代jQuery的完整指南 本文详细介绍了在现代Web开发中如何用原生JavaScript替代教程前端上一篇5分钟上手preact-render-to-string从安装到第一个HTML渲染示例下一篇layuicms2.0部署避坑指南localhost环境配置与常见问题解决创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询