Snabbdom 虚拟 dom(一)

为什么使用虚拟 Dom

提升页面性能,用最少的操作来达到最大的性能

虚拟 DOM 作用

  • 维护视图和状态的关系
  • 复杂视图情况下提升渲染性能
  • 跨平台
    • 浏览器平台渲染DOM
    • 服务端渲染 SSR(Nuxt.js/Next.js)
    • 原生应用(Weex/React Native)
    • 小程序(mpvue/uni-app)等

Snabbdom 虚拟 DOM 库

因为 Vue 2.x 内部使用的虚拟 DOM 就是结合的 Snabbdom,然后大约 200 行代码,研究这个比直接去看 Vue 源码要轻松

创建项目准备工作

新建目录 snabbdom-demo
初始化 package.json

npm init -y

本地安装 parcel

npm i parcel-bundler -D

配置 scripts 启动命令

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

在根目录下新建 index.html,并在 src 下面新建一个 01-demo.js 文件,首页引入这个 js 文件

// 首页代码
<div id="app"></div>
<script src="./src/01-basicusage.js"></script>

导入 Snabbdom

中文文档
安装 snabbdom

npm i snabbdom@2.1.0

例子1

了解 init h patch 模块的基本使用

import { init } from 'snabbdom/build/package/init'
import { h } from 'snabbdom/build/package/h'

const patch = init([])

// 第一个参数 标签 + 选择器
// 第二个参数 如果是字符串就是标签中的文本内容

let vnode = h('div#container.cls', 'hello')
let app = document.querySelector('#app')

// 第一个参数 旧的 VNode,可以是 DOM 元素
// 第二个参数 新的 VNode
// 返回新的 VNode

let oldVnode = patch(app, vnode)

vnode = h('div#container.xxx', 'hai')
patch(oldVnode, vnode)

创建子元素

const patch = init([])
// 多个子元素
let vnode = h('div#container', [h('h1', 'hello zhang'), h('p', '这是一个p')])
let app = document.querySelector('#app')
let oldVnode = patch(app, vnode)

// 	// 清除 div 中的 内容
patch(oldVnode, h('!'))

snabbdom 模块作用

  • Snabbdom 的核心库并不能处理 DOM 元素的属性/样式/事件等, 可以通过注册 Snabbdom 默认提供的模块来实现
  • Snabbdom 中的模块可以用来扩展 Snabbdom的功能
  • Snabbdom 中的模块的实现是通过注册全局的钩子函数来实现的

官方提供的模块

  • attributes
  • props
  • dataset
  • class
  • style
  • eventlisteners

举个例子

import { init } from 'snabbdom/build/package/init'
import { h } from 'snabbdom/build/package/h'

// 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 red'), h('p', { on: { click: eventHandler } }, 'hello p')])

function eventHandler() {
	console.log('点击')
}

let app = document.querySelector('#app')
patch(app, vnode)
posted @ 2022-06-10 16:15  地灵  阅读(112)  评论(0编辑  收藏  举报