虚拟DOM创建步骤与diff算法步骤

116 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第21天,点击查看活动详情

创建节点步骤

真正创建节点,将vnode创建为DOM,是孤儿节点,不会进行插入

创建一个DOM节点

判断有子节点还是有文本节点

内部是文字 document.innerText = vnode.text;

内部如果是子节点,就要递归创建节点

循环得到这个虚拟节点的children属性

创建出DOM使用createElement,创建出DOM,他的ele属性指向DOM

最后将创建的节点appendChild到 创建的节点上

vnode.elm = DOM;

返回elm,elm属性是一个纯DOM对象 return vnode.elm;

 

对比同一个虚拟节点步骤

判断新旧vnode有没有text属性

如果新vode有text属性

如果新虚拟节点中的text和老的虚拟节点的text,那么直接让新的text写入老的elm中,

如果老的elm是children,则立即会消失

 

如果新的vode没有text属性,有children

//判断老的有没有children

//老的有children,新的也有children

老的没有children,新的有children,清空老的节点内容

//遍历新的vnode的子节点,创建DOM,最后appendChild上

 

断是否为同一个虚拟节点

当新后与旧前命中的时候,此时要移动节点,移动前新指向的这个节点到老节点的旧后的后面

如何移动节点?

只要插入一个已经在DOM树上的节点,它就会被移动

制作keyMap一个映射对象,这样不用每次遍历老对象

寻找当前这项,这项在keyMap中的映射的位置序号

判断如果是undefined表示为全新的项

被加入的项不是真正的DOM节点

如果不是undefined,不是全新的项,则要移动

移动: 使用insertBefore可以实现移动

指针下移,只移动新的头

如果循环结束start比old小

则遍历新的newCh,添加到来的没有处理之前

newCh[i]此时还没有真正的变DOM,则需要调用createElement变成真正的DOM

如果start比old大

则批量删除oldStart和oldEnd指针之间的项