Virtual Dom 库

Virtual Dom 便是又普通的 js 目标来描绘 Dom 目标,由于 Dom 目标是非常巨大,而且兼容性不好,虚拟 Dom 在复杂视图中能够提升功能还能够跨平台运用。

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

创立项目

首先咱们创立一个名为 snabbdom-demo 的项目目录,然后运用 npm 初始化项目,安装 parcel 打包东西:

npm init -y
npm install parcel-bundler -D

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

"scripts": {
    "dev": "parcel index.html --open",
    "build": "parcel build index.html"
  },

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

<body>
  <div id="app"></div>
  <script src="./src/test1.js"></script>
</body>

运用示例

学习 snabbdom 的第一步便是检查 snabbdom 文档,文档中介绍了许多办法的运用,咱们重点看一下 inith 办法的运用。

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 是支撑的。

运转界面

npm run dev

咱们能够看到界面显现 Hello World,元素为 <div id="container" class="cls">Hello World</div> ,然后两秒后页面清空,元素为 <!---->

代码剖析

从代码和运转结果看,咱们能够理解 inith 函数的作用。

  1. init: 接纳包括模块的数组,并回来一个具有指定功能的 patch 函数
  2. h:接纳两个参数,第一个参数表示标签+选择器,第二个参数如果是字符串便是标签中的文本内容,如果是数组便是子元素。
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

运用

// 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')
])