本文的snabbdom源码分析采用的是0.54版本(即未用ts重写前的最后一版)html
snabbdom被用做vue的虚拟dom。本文的一个目的就是对于进入vue源码预备。
本文大体讲解,而不会彻底细化至代码行数讲解vue
说白了就是返回一个数据表示dom结构的数据对象node
则是对多重有子结构 text节点之类的数据对象进行在再处理
返回一个解析好的vnodegit
一些dom操做的api封装
结合到后面作vnode渲染到真实dom的操做
is.js 两个工具函数 一个是是否为数组 一个是是否为基本类型 也就是数字string这些文本节点github
里面放的则是一些对应的数据结构上例如property attribute之类的辅助操做算法
里面用来更新节点的属性
基本的套路都是一个for in迭代 而后内部判断patch 判断是否须要更新亦或者是删除 若是存在属性的话 且不一样确定是更新 若是新有了 旧的没有就增长 新没有了旧还有 对于一些属性直接设置false 或者是赋空便可segmentfault
这里也是一些利用classList作快速增长修改删除节点上的class的操做
基本简单的判断就是这种套路api
设置节点属性值数组
看源码能够发现 事件绑定这一步传入的参数其实是被包装的
利用函数封装了一层handleevent
handleevent里面其实是触发invokeHandler
那么从源码能够看出 实际上触发dom节点的绑定事件其实是在触发
绑定在上下文为vnode的触发器上。浏览器
props设置节点这个props是须要键值对的。通常自定义属性值在这里声明好一些,设置checked selected由于内部有一个booleanarray 其实有绑定的话只是作
property可以从attribute中获得同步;
attribute不会同步property上的值;
模拟动画帧 用requestAnimationFrame不兼容则用setTimeout
requestAnimationFrame的好处是它的刷新频率会与浏览器一致
setTimeout则有时候可能出现丢失的状况
内部封装一个两层的调用来使用,大概是两帧的意思
若是没有delayed或者remove直接更新style便可
设置节点被destory时候的style
设置删除效果也就是调用自定义的remove钩子函数。若是没有的话就调用全局的
这些定义都是根据api阅读结合源码发现的
remove钩子执行后才会删除样式
这块是在网上看的源码解读
由于diff算法应该是一个vitrual dom实现的重点了
createKeyToOldIdx 给旧节点设置key用于比对
// create => style,class,dataset,eventlistener,props,hero
// update => style,class,dataset,eventlistener,props,hero
// remove => style
// destory => eventlistener,style,hero
// pre => hero
// post => hero
这是一些钩子函数的使用api吧
init作一些模块的初始化 还有全局钩子的初始化
传入一个节点 而后对这个节点进行操做提取 转换成vnode数据对象
// remove拦截器 style里面说起的
// 对remove钩子回调作减法而后才删除节点
vnode映射真实节点
看到这里的时候对insertedVnodeQueue很不懂 究竟要干吗
而后忽然想明白了。这个大概是inserted的钩子吧- -
在每一次插入操做的时候都将节点insert
api.这类型方法能够看出来是在调用对应modules的方法
由于开始的时候就导入进来了
插入节点操做的时候都须要加入insertedVnodeQueue
子节点有子元素 也就是children的时候递归调用循环子节点生成tree
对应着一些操做以后都要触发钩子函数。
之前并不清楚钩子函数生命周期触发原理,此次却是见识了
invokeDestroyHook 手动触发destroy钩子 先触发vnode的钩子 在触发全局钩子 再递归触发子节点的钩子
removeVnodes remove操做 由于要使得remove钩子触发后才删除节点
updateChildren patchVnode 最主要的diff算法
利用先后索引的方式
进行对两树的遍历patch 复杂度是O(n)
由于比较都是在同层作比较对比patch
起点在patchVnode 而后patch过程updateChildren 而后调用updateChildrens
一个分段的伪递归
而当索引不生效 这个时候则采用传统的key-index比对
网上的一些simple vitrual dom教程
实现的是基于深度遍历作list diff
而后取得节点的变化
在作对应操做 。
snabbdom的patch等等 都是基于数据对象作的。
而一些vitrual的实现是基于树的patch
virtual-dom的一个好处就是让咱们能够从繁杂无章的dom操做中解脱,利用js对象的形式映射到dom,从而操做js数据操做dom
所谓的性能其实仍是得看你怎么用,大片的修改dom不见得virtual dom就有多好用。
打算也实现个simple dom 占坑~~(固然在path diff算法上可能不存在优化了)(占坑占坑)
snabbdom也是vue使用的virtual dom 库,emmm以后能够看看vue是怎么结合使用snabbdom的。
撒花。thanks
若是有须要详细代码解析的朋友能够联系我获取。