<><a id="user-content-" class="anchor" aria-hidden="true" href="#" ><span class="octicon octicon-link"></span></a>>
前文
因为Vue3写的时候和源码解析文章也不是特别多
也是根据一些讲谈和思否的一些文章伴着研究一些小细节
加上个人编程功底不是特别深,可能存在事实性错误
请勿当做准确资料看待
Vue编译
Vue编译主要变化感觉就是静态作用域提升以及BlockTree,在编译部分也有一定改变
感觉复杂度和封装更高了一点,但是在元素判断部分相比Vue2有更干净一点
Block Tree部分之前一直也没有用心研究
今天后端炸了,终于有个闲暇时间来研究了
为了便于理解概念,这里大部分都写了伪代码
我们在render部分
渲染Vue3大概是这样的
function renderfunction(){
return function render(ctx,cache){
with(ctx){
return (_openBlock(), _createBlock(_Fragment, null, [_createVNode(.....)]
}
}
}
其中就存在了_openBlock和createBlock
这里是为了只存储动态更新部分的vnode,而摒弃静态vnode,从而提高更新效率
export function openBlock(disableTracking = false) {
blockStack.push((currentBlock = disableTracking ? null : []))
}
openBlock非常简单,仅仅相当于push了一个空数组,该数组为CurrentBlock
而在_createVnode的函数中,会根据判断条件,对currentBlock进行push,push进去的就是我们的动态vnode
function _createVNode(args){
if(xxxx){
currentBlock.push(vnode)
}
}
在_createVNode函数执行完毕后,会把其执行结果都作为参数,再去执行_createBlock
_createBlock内部会将currentBlock的内容赋值给vnode.dynamicChildren属性上
然后将blockStack弹出
设置当前currentBlock为上一级
之后将本次vnode作为上一级的currentBlock的动态vnode,投入currentBlock中
function _createBlock(){
const vnode = createVNode()
vnode.dynamicChildren = currentBlock
blockStack.pop()
currentBlock = blockStack[blockStack.length - 1]
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