snabbdom的基本使用
前言
我们上一篇博客中介绍了虚拟DOM的基本概念及常见类库,其中常见类库有2种,snabbdom和virtual-dom,而snabbdom是vue2.x版本中所使用的,所以我们这片文章就主要来记录一下snabbdom的基本使用。
创建项目
-
打包工具为了方便使用比较简单的parcel
-
创建项目 并安装parcel
mkdir snabb-demo // 在工作目录下建立snabb-demo子目录 cd snabb-demo //进入snabb-demo 目录 yarn init --yes //初始化一个package.json文件,也可以用npm init yarn add parcel-bundler --dev // 安装parcel
-
创建目录结构,根目录下创建一个index.html,src目录下创建一个basicuse.js
其中index.html内容如下:其中html代码如下: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>snabbdom demo</title> </head> <body> <div id="app"></div> </body> <script src="./src/basicuse.js"></script>
-
在package.json中配置脚本
"scripts":{ "dev": "parcel index.html --open", "build":"parcel build index.html" }
导入snabbdom
snabbdom文档
- 英文文档:https://github.com/snabbdom/snabbdom
- 中文文档:https://github.com/coconilu/Blog/issues/152
安装snabbdom
```
yarn add snabbdom //即可安装sanbbdom,也可以安装指定版本0.7.4
```
导入snabbdom
- 采用es module 方式导入snabbdom
文档给出的示例是 var snabbdom = require(‘snabbdom’)采用的是commonJS的模块化方式引入的;我们此处需要使用es module来进行导入,所以我们去node_modules中找到snabbdom中的snabbdom.js,发现它只导出了h、thunk、init三个函数,并且都没有采用export default导出,我们学习es6知道,如果没有采用 export default,我们用es module导入的时候就要用对象的形式 {} 去接收
所以我们这样导入:import {h,thunk,init} from 'snabbdom’即可完成导入
import {h,thunk,init} from 'snabbdom'
- h函数的作用是生成一个虚拟dom,我们在vue中也在使用
- init() 是一个高阶函数,返回一个patch()
- thunk()是一种优化策略,主要优化复杂视图
snabbdom使用示例
创建一个hello world
basicuse.js代码如下:
import { h, init } from 'snabbdom'
// 此例主要实现一个hello world 实例
// init接收一个数组作为参数,该参数主要指定使用的模块列表,也可以为空
// 返回一个使用指定模块集的patch函数,此函数的作用主要是对比两个vnode的差异更新到真实DOM
let patch = init([])
// h函数
// 第一个参数:标签+选择器
// 第二个参数:如果是字符串的话就是标签中的内容
// 返回值:vnode虚拟dom
let vnode = h('div#container.cls','hello world')
let appDom = document.querySelector('#app')
// 然后利用patch函数进行内容比较与替换
// patch()函数
// 第一个参数:可以是dom元素,如果是dom则会自动将dom转换成vnode
// 第二个参数:vnode
// 返回值:vnode
let oldVnode = patch(appDom,vnode)
index.html内容
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>snabbdom demo</title>
</head>
<body>
<div id="app"></div>
</body>
<script src="./src/basicuse.js"></script>
</html>
执行yarn run dev 之后,可以看到浏览器页面中输出了hello world
效果图如下:
假设我们从服务器拿到了内容想要进行替换,可以进行如下操作即可完成
let ser = h('div',"hello snabbdom")
patch(oldVnode,ser)
页面就会输出hello snabbdom
创建一个带子元素的节点并进行替换
创建02-basicuse.js,内容如下
import { h, init } from 'snabbdom'
let patch = init([])
// h()中第二个参数如果是字符串,被认为是内容,如果是数组被任务是子元素
let vnode = h('div#container',[
h('h1','hello snabbdom'),
h('p','这是一个P标签')
])
let app = document.querySelector('#app')
let oldVnode = patch(app,vnode)
setTimeout(()=>{
vnode = h('div#container',[
h('h1','hello world'),
h('p','这是一个新的p标签内容')
]);
patch(oldVnode,vnode)
},2000)
index.html内容
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>snabbdom demo</title>
</head>
<body>
<div id="app"></div>
</body>
<script src="./src/02-basicuse.js"></script>
</html>
可以通过yarn run dev查看效果,最开始页面将id为app的div替换为一个含H1与P把标签的div,2秒后值改变为我们新设的值
如果想要清空节点内容,注意官网给出的方式是错误的
patch(oldVnode,null) //官网给出的错误清空方法
patch(oldVnode,h('!')) //正确清空节点的方法
//h('!') 创建一个注释节点替换之前节点内容
snabbdom 模块
snabbdom的核心库并不能处理元素的属性、样式、事件等,如果需要处理的话,可以使用模块来处理
常用模块
官方提供的模块有以下6个:
- attributes
- 设置dom元素的属性,使用setAttribute()
- 会对布尔类型的属性进行判断
- props
- 和attributes模块类似,设置dom的属性,但是是以element[attr] = value的形式设置的
- 不会处理布尔类型的属性
- class
- 切换类样式
- dataset
- 设置data-*的自定义属性
- eventlisteners
- 注册和移除事件
- style
- 设置行内样式、支持动画
模块使用
模块使用步骤
- 导入需要的模块
- 在init()中注册模块
- 使用h()函数创建vnode时,可以把第二个参数设置为对象,其他参数后移
代码演示
创建03-basicuse.js,内容如下:
import { h, init } from 'snabbdom'
// 1、导入模块
import style from 'snabbdom/modules/style'
import eventlisteners from 'snabbdom/modules/eventlisteners'
// 2、注册模块
var patch = init([style,eventlisteners])
// 3、使用h()函数的第二个参数存放样式、事件等,其他参数后移
let vnode = h('div',{
style:{
backgroundColor:'red' // 如果两个单词采用驼峰写法
},
on:{
click:addCount // 所有事件都写在on里
}
},[
h('h1','h1的内容,增加了背景色和click事件'),
h('p','这是一个p标签')
])
// 创建一个div,背景色为红色且绑定click事件addCount
// 包含2个孩子节点,一个是p标签,一个是h1标签
function addCount(){
alert('方法增加~')
}
let app = document.querySelector('#app')
let oldvNode = patch(app,vnode)
效果图如下:
总结一下:
- 先引入模块 import x from ‘snabbdom/modules/xx’
- init()初始化的时候是一个数组,可以传入我们需要的模块,也可不传
- 我们在h()函数的第二个参数中,可以增加相关的配置,第二个参数是一个对象。
- 如果我们需要给该节点增加子节点,则第三个参数为数组,若只是想添加节点内容则需要是字符串。