7.5 原生结合与版本迁移 全册最后一节,回答一个悬在每章身后的问题:既然原生 API 一路追平,这台 jQuery 手术台该何去何从。答案不是非此即彼——存量代码里它要与原生长期共存,新代码按路线图逐步换装,类库本身按版本规律稳步升级。本节给出共存的三条规矩、一张完整的替换路线图、跨大版本的升级三步法,以及一份去留判断清单,为全册收束。 本节摘要:共存三规矩——集合与节点互转要主动、作用边界按模块划分、 让渡 符号;迁移按路线图逐模块推进,选择器、类名、事件、请求四大块皆有直接等价物;跨大版本升级走 Migrate 三步法;去留按"存量深度、团队能力、插件依赖、浏览器目标"四项打分。 共存的三条规矩 同一页面里 jQuery 与原生并存是常态,立三条规矩能避开绝大多数互踩。
全册最后一节,回答一个悬在每章身后的问题:既然原生 API 一路追平,这台 jQuery 手术台该何去何从。答案不是非此即彼——存量代码里它要与原生长期共存,新代码按路线图逐步换装,类库本身按版本规律稳步升级。本节给出共存的三条规矩、一张完整的替换路线图、跨大版本的升级三步法,以及一份去留判断清单,为全册收束。
本节摘要:共存三规矩——集合与节点互转要主动、作用边界按模块划分、
noConflict让渡$符号;迁移按路线图逐模块推进,选择器、类名、事件、请求四大块皆有直接等价物;跨大版本升级走 Migrate 三步法;去留按"存量深度、团队能力、插件依赖、浏览器目标"四项打分。
同一页面里 jQuery 与原生并存是常态,立三条规矩能避开绝大多数互踩。
规矩一,互转主动且显式。原生查询的节点要过 jQuery 方法就包一层,jQuery 集合取裸节点就用下标:
var node = document.querySelector('.item'); $(node).addClass('seen'); // 原生成果进 jQuery 加工 var raw = $('#queue')[0]; raw.classList.add('seen'); // jQuery 成果交原生处理
规矩二,作用边界按模块划分。7.4 的功能域模块正好当边界用:一个模块内部只用一种体系,混用收敛在模块边界上,谁也不拖累谁。规矩三,符号冲突用 noConflict 解。当页面同时存在两个都想占用 $ 的库时:
var jq = jQuery.noConflict(); // 让出 $ 与 window.jQuery 的占用,返回 jQuery 自身 jq('#queue').hide(); // 此后用 jq 当刃 (function ($) { // 局部闭包内继续用 $ 书写 $('#queue').hide(); })(jq);
1.2 节的版本选型在此补全最后一块:noConflict 保证 jQuery 能在任何多库环境里体面共存,这也是老项目里 $ 突然"不是 jQuery 了"这类怪象的标准病因。
全册反复出现的原生对照在这里总装成一张图——每一块都能从 jQuery 直达原生:

换装的顺序建议从叶子模块开始:先迁类名与样式这类零风险块(classList 同名同义),再迁事件(注意命名空间要用对象表自管),最后迁 AJAX 与动画(错误处理与编排语义需要重写)。每迁一个模块跑一轮 7.4 的调试四步,绿了再迁下一个——迁移是许许多多次小手术,不是一次开膛。
还在老版本上的项目,第一步不是迁原生而是先把版本升到位。跨大版本的标准流程三步:
// 第一步:新版本与 Migrate 插件同时引入 // <script src="js/jquery-3.7.1.min.js"> // <script src="js/jquery-migrate-3.4.1.min.js"> // 第二步:全量回归,观察控制台警告 // JQMIGRATE: jQuery.fn.bind() is deprecated // ——每条警告点名一个废弃用法与位置 // 第三步:按警告清单逐一改写,全部清零后撤掉 Migrate
1.x 直升 3.x 的重点雷区按章节回看:bind、live、delegate 换 on(第 4 章);$.parseJSON、$.trim、$.type 退役(第 7 章工具节);动画与显示的边缘行为变化(第 5 章);ready 的异步化(第 1 章)。Migrate 的价值是把"哪些老写法还在被使用"从考古变成控制台逐条点名——2.1 节的选型决策里"先挂 Migrate 跑全量回归"说的就是这套动作。
最后回答去留。逐项给手头项目打分,再综合判断:
$. 用法散布多少个模块?超过一半模块深度耦合,重写成本盖过收益,留。四项里有两项以上倾向"留",就按本节的共存规矩与版本升级把现状经营好;倾向"走"的,按路线图从叶子模块起步。迁移的终点不是"消灭 jQuery",而是每个模块都待在最适合它的体系里——这也是全册从头到尾对照原生讲下来的用意:知道两岸各有什么,才谈得上选择。
背景:标本页的候诊队列模块决定试迁原生,作为整个迁移计划的第一台小手术。迁移前它是典型的 jQuery 三件套——委托点击、类名切换、局部刷新。
操作按叶子顺序推进。第一刀换类名与查询:
// 迁移前 var $items = $('#queue .item'); $items.filter('.urgent').addClass('flag'); // 迁移后 var items = document.querySelectorAll('#queue .item'); items.forEach(function (el) { if (el.classList.contains('urgent')) el.classList.add('flag'); });
第二刀换事件委托,4.4 节的原生委托模板直接上岗:
document.getElementById('queue').addEventListener('click', function (event) { var item = event.target.closest('.item'); if (item) item.classList.toggle('done'); });
第三刀换局部刷新,load 换成 fetch 加显式注入检查——只有内容来自自家网关时才允许 innerHTML,这是 6.4 安全清单在此处的落地。
fetch('fragments/queue.html') .then(function (r) { return r.text(); }) .then(function (html) { document.querySelector('#queue').innerHTML = html; // 可信来源,放行 });
结果:三刀过后模块行为与迁移前逐项对齐,回归清单全绿。解读:换装的每一步都不是发明新代码,而是把全册每章末尾的原生对照段落搬进工程——这也解释了迁移顺序为什么从叶子起步,叶子块的对照物最简单、出问题最好回退。变式:若模块里还挂着动画,把 fadeOut 换成 CSS 过渡加类名切换,脚本只管状态、过渡交给样式表,正好落在 5.2 讲过的分界线上。
noConflict。手术台熄灯,器械归位。回到导读那张知识地图——从「$」的一声开机到最后一节的康复计划,这条流水线你已经亲手走了一遍。