Snabbdom 的使用

Virtual Dom 库

Virtual Dom 就是又普通的 js 对象来描述 Dom 对象,因为 Dom 对象是非常庞大,而且兼容性不好,虚拟 Dom 在复杂视图中可以提升性能还可以跨平台使用。

Snabbdomvirtual-dom 就是两个出名的虚拟 Dom 的开源库。而 vue 内部就是引入了 Snabbdom,且它只有 200 行代码,易于学习,所以接下来要分析 Snabbdom 开源库。

创建项目

首先我们创建一个名为 snabbdom-demo 的项目目录,然后使用 npm 初始化项目,安装 parcel 打包工具:

js 复制代码
npm init -y
npm install parcel-bundler -D

修改项目的 package.json,配置 scripts:

js 复制代码
"scripts": {
    "dev": "parcel index.html --open",
    "build": "parcel build index.html"
  },

最后在项目目录下添加 index.htmlsrc/test1.js 文件,并在 index.html 中引入 src/test1.js

js 复制代码
<body>
  <div id="app"></div>
  <script src="./src/test1.js"></script>
</body>

使用示例

学习 snabbdom 的第一步就是查看 snabbdom 文档,文档中介绍了很多方法的使用,我们重点看一下 inith 方法的使用。

js 复制代码
import { init } from 'snabbdom/build/package/init'
import { h } from 'snabbdom/build/package/h'

const patch = init([])

let vnode = h('div#container.cls', 'Hello World')
// #app 占位
let app = document.querySelector('#app')
let oldVnode = patch(app, vnode)

setTimeout(() => {
    // 清除div中的内容,替换为空的注释节点
    patch(oldVnode, h('!'))
}, 2000);

这里使用从'snabbdom/build/package/init',而不是像文档中的使用'snabbdom/init'是因为 parcel 不支持 package.json 中的 exports,如果是 webpack5 是支持的。

运行界面

js 复制代码
npm run dev

我们可以看到界面显示 Hello World,元素为 <div id="container" class="cls">Hello World</div> ,然后两秒后页面清空,元素为 <!---->

代码分析

从代码和运行结果看,我们可以理解 inith 函数的作用。

  1. init : 接收包含模块的数组,并返回一个具有指定功能的 patch 函数
  2. h:接收两个参数,第一个参数表示标签+选择器,第二个参数如果是字符串就是标签中的文本内容,如果是数组就是子元素。
js 复制代码
let vnode = h('div#container', [
  h('h1', 'Hello Snabbdom'),
  h('p', '这是一个p')
])
  1. patch : 对比两个 vnode,把两个 vnode 的差异更新到真实 Dom 上。第一个参数为旧的 VNode,可以 vnode 也可以是真实 DOM 元素,如果是真实 DOM 元素,在内部会转换为 vnode。第二个参数为新的 VNode。返回新的 VNode,可以作为下一次 patch 的旧的 VNode

模块

Snabbdom 的核心库并不能处理 DOM 元素的属性、样式、事件等,可以通过注册 Snabbdom 提供的模块来实现。

Snabbdom 官方提供了6个模块attributespropsdatasetclassstyleeventlisteners

使用

js 复制代码
// 1. 导入模块
import { styleModule } from 'snabbdom/build/package/modules/style'
import { eventListenersModule } from 'snabbdom/build/package/modules/eventlisteners'

// 2. 注册模块
const patch = init([
  styleModule,
  eventListenersModule
])

// 3. 使用h() 函数的第二个参数传入模块中使用的数据(对象)
let vnode = h('div', [
  h('h1', { style: { backgroundColor: 'red' } }, 'Hello World'),
  h('p', { on: { click: eventHandler } }, 'Hello P')
])
相关推荐
To_OC2 小时前
别再串行写 await 了,Promise.all 才是并行请求的正确打开方式
前端·javascript·promise
vipbic3 小时前
中后台越做越乱后,我用插件化把它救回来了
前端·vue.js
Hyyy3 小时前
Computer Use 适合做什么,不适合做什么——一次真实使用后的思考
前端
小和尚同志3 小时前
前端 AI 单元测试思考与落地
前端·人工智能·aigc
invicinble4 小时前
c端系统,其实更像一个信息展示平台
前端
李姆斯5 小时前
管理是否可以被完全量化
前端·产品经理·团队管理
名字还没想好☜6 小时前
Next.js 中间件实战:鉴权、重定向与 A/B 分流
开发语言·前端·javascript·中间件·react·next.js
广州灵眸科技有限公司6 小时前
瑞芯微RV1126B开发板(EASY-EAI-PI2) INI文件操作
java·前端·javascript·网络·人工智能
江华森7 小时前
Web 开发基础:HTTP 与 REST
前端·网络协议·http
IT_陈寒7 小时前
Redis的KEYS命令把我搞崩溃了,改用SCAN才活过来
前端·人工智能·后端