Vue 虚拟DOM,diff算法源泉 sanbbdom

1 sanbbdom是一个专注于简单性、模块化、强大特性和性能的虚拟DOM库。

在这里插入图片描述
官网: https://github.com/snabbdom/snabbdom
虚拟DOM是真实DOM转换出来的js层级对象,用来表示真实DOM得信息,diff算法是再新老虚拟DOM进行比较,以此算出更改的最小量更新,并渲染到真实DOM去。

sanbbdom核心就是一个h函数,和一个patch函数,前者可以返回一个虚拟DOM节点,后者可以将虚拟DOM节点插入DOM中,

这里得源码可以npm i -S snabbdom然后在node-module的文件就能看到。
我这里是删了源码,然后自己来模范实现h.

这里主要是简单实现h函数

先看H函数的用法
在这里插入图片描述
在这里插入图片描述
其实跟React.createElement类似的,也是{标签,属性,字节点},
打印一下看看在这里插入图片描述

可以看到还多了三个属性,elm表示要挂载的DOM节点,key值是唯一标识,text是内容

手写简单H函数,其实不难,按照传入的东西返回一个虚拟DOM节点对象。

传入信息给H函数,返回一个虚拟节点Vnode,这个Vnode也是一个函数,接受节点信息返回一个对象,跟React内部相似,React也是将节点传入React.createElement,然后返回的也是ReactELement函数的调用,在这里插入图片描述
在这里插入图片描述
接下来看H函数
在这里插入图片描述

在这里插入图片描述
接着,完成H函数的编写,我们假设我们每次都传入三个值,h(div,{},h())
先看一下调用
在这里插入图片描述
这里出现第三个参数又调用H函数的,此时应该挺多人想到函数递归调用,但其实不用,因为H()的时候,已经调用了,实际上H()就=== {xxx},因为已经调用了,所以不用再H函数里面拿到这些数据的时候在调用。
看Vnode函数在这里插入图片描述
再看H,函数,主要是对第三个参数的一个处理,在这里插入图片描述
首先我们假设他只能传三个参数,在这里插入图片描述
其次判断文本,若是数字或者字符串,直接返回Vnode在这里插入图片描述
接着判断数组,数组其实就是里面三个H()。也就是三个{},[{},{},{}],并且三个里面都至少含有sel属性。
那我们就将他们一个个Push进数组,作为chilren传过去。
在这里插入图片描述
接着判断第三个参数为H(),这个其实就是第三个参数传入一个{},而且这个对象含有sel,我们直接将他作为children的第一个数,返回Vnode就行。
如图
在这里插入图片描述
在这里插入图片描述
简单版H函数就封装好了,

初识DIFF算法

接着就是patch函数,这个函数就是将虚拟DOM节点转化为真实的DOM,有点类似与ReactDom.render函数。

先看snabbdom的patch函数的用法。
在这里插入图片描述
我先Vnode上树,然后监听点击事件,一点击就改变DOM

点击后
在这里插入图片描述
为了验证她是通过diff算法,
在这里插入图片描述
在这里插入图片描述
点击后前面两个DOM不变,故证明他不是完全替换,是对比后替换。

接着我们试试从第一位插入,在这里插入图片描述
在这里插入图片描述
可以看到,他进行暴力拆迁了,没有直接插入,这是为什么呢!!这就是Key值得重要作用了!!!!相信React,Vue得小伙伴就知道key值得作用,让我们试试加上Key值JIS

在这里插入图片描述
有没有一下子对KEY得认识豁然开朗,没错这里强行补充一波key值得作用,key值就是告诉diff算法,在更新前后该元素是同一元素,有助于diff算法识别元素是新增的还是原来的被偏移到这里来的。大大提高虚拟DOM得性能,而不用每次拆掉全部重新创建。而且一般不用索引作为KEY值,当数组改变时,索引值常常会发生改变,导致大量Key值失效,而且相同长度得索引得key值是一样的,可能出现更换了数组UI却不更新的现象,因为Key是一样的。第二就是随机值的话,每次的KEY值都不一样,对DIFF算法来说都相当于新增的元素,故作用不大。

当我们不同虚拟节点时

在这里插入图片描述
在这里插入图片描述
可以看到,当ul变成ol时,diff算法是暴力拆迁的

当我们跨层比较时

在这里插入图片描述
在这里插入图片描述
可以看到,当我们跨城时,diff也不会精细化比较,

diff算法的关键:

1,Key值很重要,它用于告诉diff算法哪些元素是更新前后不变的。
2,只有是同一虚拟节点,diff算法才会进行精良化比较,否则都是暴力拆迁。
如何算同一虚拟节点呢,选择器相同并且key相同则算。
3,对于跨层的节点,diff算法不进行精良化比较。
因为23的情况在实际开发中是几乎没有用到的,diff算法也是比较人性化的,也不是全能的。

猜你喜欢

转载自blog.csdn.net/lin_fightin/article/details/114555317