⌨️ 第六章 Web技术与安全
📄 本篇一句话

jQuery 是 DOM 操作的语法糖(写得少、兼容好,2026 年仍在 66.5% 的网站服役);虚拟 DOM 是它的反面教材改进版(先在内存里 diff,再把最小改动打到真 DOM)——一个让 DOM 好写,一个让 DOM 少写。

📝 在本章的位置

上游:6-7 的 DOM 与 Ajax 是两者的作用对象。这是本章「技术现状」信息量最大的一篇:jQuery 讲部署惯性,虚拟 DOM 讲框架时代的性能账。

一、jQuery(2006):把 DOM 操作变顺滑

原生 DOM 三大痛点 → jQuery 三板斧:

// 原生:查节点、绑事件、改样式,各浏览器 API 曾有差异
document.getElementById("btn").addEventListener("click", function () { ... });

// jQuery:一个 $ 走天下
$("#btn").on("click", function () { ... });          // 选择器(抄 CSS 的作业)
$("li:even").css("color", "red");                     // 链式调用
$("#box").load("/api/panel");                         // Ajax 一行

二、虚拟 DOM:少动真 DOM 的记账法

6-7 说过 DOM 操作贵(重排重绘)。虚拟 DOM 的思路:

① 数据变化 → 在内存里生成新虚拟树(轻量 JS 对象,动它不花钱)
② diff 新旧两棵树 → 算出「到底哪几个节点变了」
③ 把最小补丁一次性打给真 DOM
// 概念演示:手写一个 mini diff(内存对象层面,不碰真 DOM)
const oldV = { tag: "ul", children: ["A", "B", "C"] };
const newV = { tag: "ul", children: ["A", "X", "C"] };

function diff(oldTree, newTree) {
  const patches = [];
  for (let i = 0; i < Math.max(oldTree.children.length, newTree.children.length); i++) {
    if (oldTree.children[i] !== newTree.children[i]) {
      patches.push({ index: i, from: oldTree.children[i], to: newTree.children[i] });
    }
  }
  return patches;
}
console.log(diff(oldV, newV));
// [{index: 1, from: "B", to: "X"}] —— 只有 1 号位变了

三、一条主线:把「手」从 DOM 上拿开

时代 写法 心智
原生 JS 手动查节点、手动改 你是施工队
jQuery 语法糖+兼容层 你还是施工队,工具更好用
React/Vue 声明界面+虚拟 DOM 你画图纸,框架施工

每一步都在降低「同步数据与界面」的手工量——正是 6-6 MVVM 的兑现。

动手 Demo:jQuery 风格 vs 原生,同一件事两种写法

<!-- demo_jq.html:给列表奇偶行上色 -->
<!DOCTYPE html>
<html><head><meta charset="UTF-8"><title>斑马纹</title></head>
<body>
<ul id="list"><li>HTML</li><li>CSS</li><li>JS</li><li>SQL</li><li>Git</li></ul>
<script>
// 原生写法(任何浏览器直接跑)
const items = document.querySelectorAll("#list li");
items.forEach((li, i) => {
  if (i % 2 === 0) li.style.background = "#f0f7ff";
});
console.log("原生:", items.length, "行处理完毕");

// jQuery 写法(引库后一行):
// $("#list li:even").css("background", "#f0f7ff");
</script>
</body></html>

看到什么算成功:1、3、5 行有浅蓝底,控制台打出「原生:5 行处理完毕」。注释里那行 jQuery 与循环等价——这就是「写得少」的全部含义。

读结果:jQuery 的 :even 选择器把循环藏进了库;如今原生 API 早已吸收了这些好设计(querySelectorAll 就是当年jQuery 逼出来的标准化)。

30 秒实验

F12 控制台跑:

// 亲自感受虚拟 DOM 要解决的问题:真 DOM 操作的真实开销
console.time("1000次真DOM插入");
for (let i = 0; i < 1000; i++) {
  document.body.appendChild(document.createTextNode("x"));
}
console.timeEnd("1000次真DOM插入");

const frag = [];                    // 换成内存里攒字符串(模拟虚拟DOM攒补丁)
console.time("1000次内存攒+一次插入");
for (let i = 0; i < 1000; i++) frag.push("x");
const span = document.createElement("span");
span.textContent = frag.join("");
document.body.appendChild(span);
console.timeEnd("1000次内存攒+一次插入");

看到什么算成功:两种方式页面都多出 1000 个 x;第二个计时通常明显更短——在内存攒好了再一次性动真 DOM,虚拟 DOM 的账就是这么算的。

常见误区

自测三问(点击展开) 1. **jQuery 当年靠什么统治?现在靠什么续命?** 答:当年靠跨浏览器兼容+语法糖;现在靠 66.5% 的存量部署惯性。 2. **虚拟 DOM 三步是什么?** 答:内存建新树 → diff 新旧树 → 最小补丁打给真 DOM。 3. **虚拟 DOM 一定比直接操作 DOM 快吗?** 答:不一定——diff 有成本;它赢在大量更新下的整体最优与可维护性。

相关笔记