李恒道 发表于 2022-3-21 16:38:08

Vue3源码Block Tree问题

#

# 前文

因为Vue3写的时候和源码解析文章也不是特别多

也是根据一些讲谈和思否的一些文章伴着研究一些小细节

加上个人编程功底不是特别深,可能存在事实性错误

请勿当做准确资料看待

# Vue编译

Vue编译主要变化感觉就是静态作用域提升以及BlockTree,在编译部分也有一定改变

感觉复杂度和封装更高了一点,但是在元素判断部分相比Vue2有更干净一点

Block Tree部分之前一直也没有用心研究

今天后端炸了,终于有个闲暇时间来研究了

为了便于理解概念,这里大部分都写了伪代码

我们在render部分

渲染Vue3大概是这样的

```js
function renderfunction(){
return function render(ctx,cache){
   with(ctx){
       return (_openBlock(), _createBlock(_Fragment, null,
   }
}
}
```

其中就存在了_openBlock和createBlock

这里是为了只存储动态更新部分的vnode,而摒弃静态vnode,从而提高更新效率

```js
export function openBlock(disableTracking = false) {
blockStack.push((currentBlock = disableTracking ? null : []))
}
```

openBlock非常简单,仅仅相当于push了一个空数组,该数组为CurrentBlock

而在_createVnode的函数中,会根据判断条件,对currentBlock进行push,push进去的就是我们的动态vnode

```js
function _createVNode(args){
if(xxxx){
    currentBlock.push(vnode)
}
}

```

在_createVNode函数执行完毕后,会把其执行结果都作为参数,再去执行_createBlock

_createBlock内部会将currentBlock的内容赋值给vnode.dynamicChildren属性上

然后将blockStack弹出

设置当前currentBlock为上一级

之后将本次vnode作为上一级的currentBlock的动态vnode,投入currentBlock中

```js
function _createBlock(){
   const vnode = createVNode()
   vnode.dynamicChildren = currentBlock
   blockStack.pop()
   currentBlock = blockStack
   if (currentBlock) {
    currentBlock.push(vnode)
   }
return vnode
}
```

最后在更新的过程中

会根据dynamicChildren判断进行局部更新还是child全部更新

如果是根据局部动态更新

则是根据dynamicChildren读取到数据

遍历dynamicChildren数组

然后循环调用patch

这样更新的时候仅与dynamicChildren的数量多少有关

而与静态节点的数量无关

这样会提高更新过程的效率

也就是Block Tree的意义所在

# 结语

每次写这类文章真的是战战栗栗...

# 参考

https://segmentfault.com/a/1190000022442171

https://www.cnblogs.com/everlose/p/12853402.html

https://wuchwuw.github.io/vue-next-analysis/runtime-core/vnode.html#vnode

https://toutiao.io/posts/2cjs75p/preview
页: [1]
查看完整版本: Vue3源码Block Tree问题