diff算法,snabbdom 库

Scroll Down

虚拟DOM

  1. 用JS对象描述DOM的层次结构
  2. DOM转换虚拟DOM,属于模板编译原理

编译原理

  1. JS编译原理:编译(词法分析、语法分析、代码生成)、JS引擎执行
  2. 模板编译(模板 - 模板编译 - 渲染函数):
    a、解析器:将模板解析成AST
    b、优化器: 遍历AST,检测出所以静态子树
    c、代码生成器:将AST转换成渲染函数

snabbdom 库

  1. 主程序由ts编写,可打包build成js,*.d.ts属于编译打包后的预留文件
  2. DOM库
  3. 运行时,必须安装webpack5.0

源码分析

h函数(作用: 用来产出生虚拟节点)(虚拟节点需要函数patch,渲染到真实DOM显示)

调用: h('div', 'hello')
结果:(elm为空,说明没有渲染到页面DOM上)

{
  children:..
  data:...
  elm:...
  sle:...
}

patch函数

特点

1.最小量更新

例如:

<ul>
<li> A</li>
<li> B</li>
</ul>

更新为

<ul>
<li> A</li>
<li> B</li>
<li> C</li>
</ul>

此时元素A、B不更新,只更新C。

key的重要性: key是节点唯一标识。告诉diff算法,元素是更新前后同一个节点.

例如:

<ul>
<li> A</li>
<li> B</li>
</ul>

更新为

<ul>
<li> C</li>
<li> A</li>
<li> B</li>
</ul>

此时元素A、B更新了,如果加key则不更新。

2. 同一个虚拟节点,才进行最小量更新,否则暴力删除旧的,添加新的虚拟节点

例如:

<ul>
<li> A</li>
<li> B</li>
</ul>

更新为

<ol>
<li> A</li>
<li> B</li>
</ol>

此时,ul与ol不一样所以旧的ul节点将会直接删除

3.虚拟节点只会同层比较,否则暴力删除旧的,添加新的虚拟节点

例如:

<div>
<ul>
<li> A</li>
<li> B</li>
</ul>
</div>

更新为

<div>
<div>
<ul>
<li> A</li>
<li> B</li>
</ul>
</div>
</div>

此时,新的节点div与旧的ul节点同层,但内容不一致,因此旧的ul直接删除

流程

  1. 第一步: 判断oldVnode是虚拟节点还是DOM节点,如果不是将oldVnode转换成虚拟节点。
  2. 第二步: 判断oldVnode和newVnode是不是同一个节点,如果不是,将暴力删除旧的,插入新的。否则进行最小量更新精细化比较。
判断是否同一个虚拟节点原理(旧节点的key要和新节点的key相同且旧节点的选择器要和新节点的选择器相同)

精细化比较算法

1、判断newVnode与oldVnode是否同一个对象
2、判断newVnode是否有text属性
3、判断oldVnode是否有children属性

比较大概思想

两个虚拟DOM遍历,四个索引命中查找,命中其中一个,就不再进行命中判断、继续下一个判断流程;如果没有命中,就需要循环查找新虚拟node在旧虚拟node是否存在。
1、新虚拟Node前序索引与旧虚拟node前序索引比较
2、新虚拟Node倒序索引与旧虚拟node前序索引比较(这种情况命中,新虚拟Node指向Node移动到旧的node之后)
3、新虚拟Node倒序索引与旧虚拟node倒序索引比较(这种情况命中,新虚拟Node指向Node移动到旧的node之前)