快捷搜索:

详解Vue3中对VDOM的改进

详解Vue3中对VDOM的改进

  黑客编程软件vue-next 对virtual dom的patch更新做了一系列的优化,从编译时加入了 block 以减少 vdom 之间的对比次数,另外还有 hoisted 的操作减少了内存的开销。本文写给自己看,做个知识点记录,如有错误,还请不吝赐教。

  VDOM的概念简单来说就是用js对象来模拟真实DOM树。由于MV**的架构,真实DOM树应该随着数据(Vue2.x中的data)的改变而发生改变ASP编程,这些改变可能是以下几个方面:

  Vue框架要做的其实很单一:在用户改变数据时,正确更新DOM树,做法就是其核心的VDOM的patch和diff算法。

  在Vue2.x中,当数据改变后就要对所有的节点进行patch和diff操作。如以下DOM结构:

  预期的结果是页面出现新的一个li元素,内容就是 a new li item,Vue2.x中是通过patch时对 ul 元素对应的 vnode 的 children 来进行 diff 操作,具体操作在此不深究,但是该操作是需要比较所有的 li 对应的 vnode 的。

  正是由于2.x版本中的diff操作需要遍历所有元素,本例中包括了 span 和 第一个li元素,但是这两个元素是静态的,不需要被比较的,不论数据怎么变,静态元素都不会再更改了。vue-next在编译时对这种操作做了优化,即 Block。

  我们可以看到调用了 openBlock 和 createBlock 方法,这两个方法的代码实现也很简单:

  更加详细的注释还请看源代码中的注释,写的十分详尽,便于理解。这里面 openBlock 就是初始化一个块,createBlock 就是对当前编译的内容生成一个块,这里面的这一行代码:vnode.dynamicChildren = currentBlock EMPTY_ARR 就是在收集动态的子节点,我们可以再看一下编译时运行的函数:

  上述函数是在模板编译成ast之后调用的生成VNode的函数,所以有patchFlag这个标志,如果是动态的节点,并且此时是开启了Block的话,就会将节点塞入Block中,这样 createBlock返回的 VNode 中就会有 dynamicChildren 了。

  到此为止,通过本文中案例经过模板编译和render函数运行后并经过了优化以后生成了如下结构的vnode:

  本文没有深入讲解代码的实现层面,一是因为自己实力不济还在阅读源码当中,二是我个人认为阅读源码不可钻牛角尖,从大局入眼,再徐徐图之,先明白了各个部分的作用后带着思考去阅读源码能收获到的应该更多一些。

您可能还会对下面的文章感兴趣: