当前位置:   article > 正文

Vue3的编译优化:Block树和PatchFlags_vue3 patchflag

vue3 patchflag

注:本文只是介绍实现原理,并非常规源码解读

众所周知,Vue中的tamplate会被编译为渲染函数,渲染函数执行生成DOM子树,然后根据组件实例的状态执行mount或patch,如果patch,diff算法会对比两颗子树并进行更新。

观察这段模板:

<div>
  <div>HelloVue!</div>
  <p>{
  { text }}</p>
</div> 
  • 1
  • 2
  • 3
  • 4
  • 5

这段模板对应的虚拟DOM如下:

{
  tag:'div',
  children:[
  {tag:'div',children:'HelloVue'},
  {tag:'p,children: _context.text}
  ]
} 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

传统diff算法对比DOM树更新流程:

1.对比外层div,它的props,和它的子节点,
2.对比内层div,它的props,和它的文本子节点
3.对比内层p,它的props,和它的文本子节点, 
  • 1
  • 2
  • 3

可以看到diff算法做了很多没啥意义的对比,这段代码其实只有text绑定了渲染上下文中的内容,其余内容都是静态内容,所以虚拟DOM只需要对比p标签的文本节点就可以完成内容更新,从而提升性能。但是从上面的虚拟DOM可以看到,运行时其实没办法知道哪个文本节点是动态节点,children数组只是两个普通的vnode

Blocks和patchFags

还是相同的一段模板:

<div>
  <div>HelloVue!</div>
  <p>{
  { text }}</p>
</div> 
  • 1
  • 2
  • 3
  • 4
  • 5

我们很容易就能看出来只有p标签含有动态内容,Vue3的模板经过编译后,可以把从模板中提取到这个信息附着到对应的vnode上,可以看到编译后的vnode中p标签多了一个patchFlag属性。

{
  tag:'div',
  children:[
  {tag:'div',children:'HelloVue'},
  //patchFlag等于1说明这个节点的textContent是动态内容
  {tag:'p,children: _context.text,patchFlag: 1 } 
  ]
} 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

patchFlag属性可以让运行时知道这个vnode是一个含有动态内容的vnode(后面简称动态vnode),而且根据这个属性的值还可以精准的判断标签的动态部分到底在哪。所以可以在创建VNode的时候,把Vnode子节点中的被patchFlag标记的动态vnode提取出来(这个提取过程后面会讲到),保存在它自己的dynamicChildren数组内。我们把含有这个dynamicChildren数组的VNode就叫做一个block,block不只会提取到children的动态VNode,还可以提取到所有子代动态VNode。

当然vnode也并不是凭空产生的,而是由render函数产生,但是render函数不会直接返回vnode,要通过辅助函数createVNode()

createVNode的实现大概如下:

 function createVNode(tag,prop
    声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小桥流水78/article/detail/751928
    推荐阅读
    相关标签
      

    闽ICP备14008679号