Snabbdom 简介与快速上手
🎯 引言
学完这篇文章,你将明白虚拟 DOM到底是什么、Snabbdom 是做什么的,以及它和 Vue2 之间的关系。我们还会一起搭建练习环境,用不到 20 行代码完成第一次虚拟 DOM 渲染。
🧱 什么是虚拟 DOM
我们知道,页面是由一个个 DOM 元素组成的。直接操作 DOM 有两个麻烦:一是写起来繁琐,二是频繁改动会触发浏览器反复重排重绘,性能开销大。
虚拟 DOM(Virtual DOM)就是用 JavaScript 对象来描述 DOM 结构。比如一个真实的 div:
<div id="app">Hello</div>
用虚拟 DOM 描述,就是一个普通的 JS 对象:
const vnode = {
sel: 'div#app',
text: 'Hello'
};
你可以把它理解成施工图纸:真实 DOM 是盖好的房子,虚拟 DOM 是图纸。改动时先画一张新图纸,把新旧图纸对比一遍,只在房子上改动有差异的地方,而不是整栋推倒重建。
🧱 Snabbdom 是什么
Snabbdom 是一个专注于虚拟 DOM 的 JavaScript 库,名字来自瑞典语,意为"敏捷、迅速"。它有两个鲜明的特点:
- 小巧:核心代码只有约 200 行,没有历史包袱,非常适合学习。
- 模块化:核心只负责创建和对比虚拟节点,样式、属性、事件等功能全部通过"模块"按需加载。
最值得一提的是:Vue2 的虚拟 DOM 实现,正是基于 Snabbdom 改造而来的。也就是说,学好 Snabbdom,就等于摸到了 Vue2 底层的脉搏。
🚀 搭建练习环境
本课程环境使用 Node.js v22.0.0,对应的 Snabbdom 版本为 3.6.4。
虚拟 DOM 最终要渲染到浏览器页面上,我们用 Vite 创建一个最简项目(Vite 在 Stage4 已经学过):
npm create vite@latest snabbdom-demo -- --template vanilla
cd snabbdom-demo
npm install
npm install snabbdom@3.6.4
启动开发服务器:
npm run dev
浏览器打开终端里提示的地址(通常是 http://localhost:5173),看到 Vite 的欢迎页就说明环境没问题了。
📦 第一个示例:渲染并更新页面
打开 main.js,把模板自带的代码清空,写入:
import { init, h } from 'snabbdom';
// init 用来创建 patch 函数,先传一个空数组,第三篇再细讲
const patch = init([]);
// 用 h 函数创建一个虚拟节点:一个 id 为 container 的 div
const vnode = h('div#container', 'Hello Snabbdom');
// 把虚拟节点渲染到页面上
const container = document.getElementById('app');
patch(container, vnode);
index.html 里需要一个挂载点(vanilla 模板自带):
<div id="app"></div>
保存后浏览器里就能看到 Hello Snabbdom。此时页面结构变成了:
<div id="container">Hello Snabbdom</div>
接着试试更新。在代码末尾追加:
// 画一张"新图纸",对比后更新页面
const newVnode = h('div#container', '你好,虚拟 DOM');
patch(vnode, newVnode);
页面文字会瞬间变成"你好,虚拟 DOM"。注意第二次调用 patch 传的是上一次的 vnode 和新 vnode——这就是"新旧图纸对比"的过程。
这段代码涉及三个核心角色,先记住名字,后面每篇都会深入:
| 角色 | 作用 |
|---|---|
h | 创建虚拟节点(画图纸) |
init | 创建 patch 函数(可注册模块) |
patch | 对比并更新真实 DOM(按图施工) |
🧾 小节总结
- 虚拟 DOM 是用 JavaScript 对象描述 DOM 结构,更新时对比新旧两棵树,只改差异部分。
- Snabbdom 是一个小巧、模块化的虚拟 DOM 库,核心仅约 200 行代码。
- Vue2 的虚拟 DOM 基于 Snabbdom 改造,学它就是学 Vue2 的底层。
- 本课程使用 Node.js v22.0.0 和 Snabbdom 3.6.4,用 Vite vanilla 模板搭建练习环境。
- 三个核心角色:
h创建虚拟节点,init创建patch,patch负责渲染和更新。
❓ 知识问答
Q1:虚拟 DOM 一定比直接操作 DOM 快吗?
A:不一定。虚拟 DOM 的价值在于"用 JS 计算换取最少的 DOM 操作",并提供更好的开发体验。首次渲染时它反而多了一层计算开销。它不是银弹,但在数据频繁变化的界面里收益巨大。
Q2:Snabbdom 能直接用来做真实项目吗?
A:可以,但它定位偏底层,一般被框架集成使用(如 Vue2)。日常开发我们更常用 Vue、React 这类框架,学 Snabbdom 主要是为了理解底层原理。
Q3:为什么不直接用 script 标签引入 Snabbdom?
A:Snabbdom 3.x 以 ES 模块发布,配合 Vite 这类开发工具最省事,保存代码还能自动刷新页面,学习体验更好。
Q4:h 函数的名字是什么意思?
A:h 是 hyperscript 的缩写,意为"用脚本(JavaScript)书写 HTML",是虚拟 DOM 领域约定俗成的命名。
🧪 小练习
- 按本篇步骤创建
snabbdom-demo项目并安装snabbdom@3.6.4。 - 修改
main.js,渲染出一个id为box、内容为"我的第一个虚拟节点"的section元素,然后再把它更新为"内容更新啦"。
import { init, h } from 'snabbdom';
const patch = init([]);
// 请在这里编写代码
🎉 恭喜你已经完成了 Snabbdom 的入门!下一篇我们深入学习 h 函数,看看它能描述出多么复杂的页面结构。
