Appearance
Snabbdom基本使用
创建项目并引入文件
- 创建项目,打包使用parcel
bash
npm init -y
npm i parcel-bundle --save-dev
- 设置package.json的scripts
js
"scripts": {
"dev": "parcel index.html --open",
"build": "parcel build index.html"
}
- 创建
src/01.js
,创建index.html
并引入js文件
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>snabbdom-demo</title>
</head>
<body>
<div id="app"></div>
<script src="./src/01.js/"></script>
</body>
</html>
- 安装snabbdom
npm i snabbdom --save-dev
- 导入snabbdom模块, 遇到问题参考 snabbdom导入问题
- CommonJS方式
js
const { h } = require('snabbdom/build/package/h')
const { thunk } = require('snabbdom/build/package/thunk')
const { init } = require('snabbdom/build/package/init')
- ESModules方式
js
// 导入
import { h } from 'snabbdom/build/package/h'
import { thunk } from 'snabbdom/build/package/thunk'
import { init } from 'snabbdom/build/package/init'
console.log(h)
console.log(thunk)
console.log(init)
函数简单介绍
init()、h()、thunk()这三个函数是sanbbdom的核心,实现最基本的功能。
名词解释
VNode:即虚拟DOM,用来描述真实DOM的。
init函数
高阶函数,返回patch()
- 参数:一个数组形式的参数,里面可以传入模块
- 返回值:patch函数
js
let patch = init([])
patch函数
核心函数
- 作用:对比两个虚拟DOM(VNode)的差异,将差异更新到真实DOM
- 参数
- 第一个参数:可以是VNode,也可以是真实DOM元素,内部会把DOM元素转换成VNode,再与第二个参数进行对比
- 第二个参数:VNode
- 返回值:VNode
h函数
返回虚拟节点VNode,创建render的时候里面有见过
- 作用:h函数用来返回虚拟DOM
- 参数
- 第一个参数表示标签+选择器
- 第二个参数如果是字符串就是设置标签中的内容
- 第二个参数如果是数组就插入子节点,每个元素都是一个h函数
- h中如果传入注释节点形式是:h('!')
js
// 第二个参数是字符串
let vnode = h('div#container.cls','Hello world')
// 第二个参数是数组
let vnode = h('div#container',[
h('h1', 'Hello Snabbdom'),
h('p', '这是一个p标签')
])
thunk函数
一种优化策略,可以在处理不可变数据时使用
基本用法
Hello World
js
// 01.js
import { h } from 'snabbdom/build/package/h'
import { init } from 'snabbdom/build/package/init'
// 1. hello world
// 先用init方法返回一个patch函数,在用h方法创建一个虚拟DOM
let patch = init([])
// 创建虚拟DOM(用来描述真实DOM的)
let vnode = h('div#container.cls','Hello world')
// 上面只有一个VNode,在index.html中有一个app元素是用来占位的,之后会替换
// 所以先获取app元素
let app = document.querySelector('#app')
// 利用patch更新DOM
let oldVnode = patch(app, vnode)
// 2. 从服务器中获取了新的数据要进行更新
vnode = h('div','Hello Snabbdom')
// 利用patch方法将新的vnode和旧的vnode进行比较
oldVnode = patch(oldVnode,vnode)
在2执行之前,页面显示Hello world
,在执行2之后,页面显示Hello Snabbdom
在元素中创建子元素
- 创建src/02.js,并在index.html中引用
- 在02.js中写
js
// 导入
import { h } from 'snabbdom/build/package/h'
import { init } from 'snabbdom/build/package/init'
// 通过init初始化一个patch函数
let patch = init([])
// 创建一个div,在里面放子元素
// 第二个元素可以是一个数组,里面包含了子元素的信息
let vnode = h('div#container',[
h('h1', 'Hello Snabbdom'),
h('p', '这是一个p标签')
])
// 获取占位dom元素app
let app = document.querySelector('#app')
// 比较元素渲染页面
patch(app, vnode)
- 在服务器获取新的信息如何更新?
js
// 给patch的结果赋值一个旧VNode
let oldVnode = patch(app, vnode)
// 在服务器获取了新的内容,2s后更新页面
setTimeout(() => {
vnode = h('div#container',[
h('h1','Hello world'),
h('p','hello p')
])
patch(oldVnode, vnode)
}, 2000)
可以看到页面上发生了变化
清空页面元素
官方给出的清除方法是patch(oldVnode, null)
但是用这种方法会报错,所以可以采用创建注释节点的方式清空页面所有元素
js
...
patch(oldVnode, h('!'))
Snabbdom模块
Snabbdom 的核心库并不能处理元素的属性/样式/事件等,如果需要处理的话,可以使用模块。
常用模块
官方提供了 6 个模块
- attributes
设置 DOM 元素的属性,内部使用的是 setAttribute (),会判断并处理布尔类型的属性,如selected等
- props
和 attributes 模块相似,设置 DOM 元素的属性,内部使用的时候是element[attr] = value的形式,不处理布尔类型的属性
- class
切换类样式
注意:给元素设置类样式是通过h函数设置的
- dataset
设置 data-* 的自定义属性
- eventlisteners
注册和移除事件
- style
设置行内样式,支持动画 delayed/remove/destroy,增加了额外的功能,增加了相应的属性。
模块使用
- 创建src/03.js和修改index.html的引用
- 在03.js中导入模块
如果你是0.7.4版本,采用下面的写法
js
import style from 'snabbdom/modules/style'
import eventlisteners from 'snabbdom/modules/eventlisteners'
如果是1.0.1之后的版本,现在是2.0.1版本,采用下面的写法
js
import { styleModule } from 'snabbdom/build/package/modules/style'
import { eventListenersModule } from 'snabbdom/build/package/modules/eventlisteners'
- init() 中注册模块,init中的数组就是用来传入模块的。
js
let patch = init([
styleModule,
eventListenersModule
])
- 使用 h() 函数创建 VNode 的时候,可以把第二个参数设置为对象,通过对象设置行内样式、事件等等,其他参数往后移。
js
let vnode = h('div',{
style: {
backgroundColor: 'red'
},
on: {
click: eventHandler
}
},[
h('h1','Hello snabbdom'),
h('p','这是一个p标签')
])
// 点击事件
function eventHandler () {
console.log('click me~')
}
- 获取app真实DOM,并比较渲染到页面上
js
let app = document.querySelector('#app')
patch(app, vnode)
可以看到页面上有了背景为红色的内容。