大概几集下饭剧时间就能懂的VUE3原理
大家好,我是卡颂。
最近中午没胃口,找来VUE
源码相关视频来当下饭剧。几顿饭下去,人胖了,VUE
也整明白了。
文章图片
这篇文章为你带来一份VUE3
原理速成指南。
模块划分
如果我们用VUE的模版语法定义:
hello
最终
VUE
会帮我们在浏览器中渲染对应的DOM节点
。这之间对这段节点的描述会经历4次变化,横跨编译时与运行时:
文章图片
模版语法在编译时会被编译器转化为render函数,类似:
render(h) {
return h('div', 'hello');
}
在运行时,render函数执行后返回的h函数的执行结果就是
VNode
(也就是虚拟DOM
),类似:{
tag: "div",
children: [
{
text: "Hello"
}
]
}
最终,
VUE
根据VNode
的信息,在浏览器渲染对应DOM
。那么,是谁在驱动这一流程?
mount和patch 【大概几集下饭剧时间就能懂的VUE3原理】组件有两种不同的渲染逻辑:首次渲染和更新。
首次渲染意味着从无到有,比如上文的
VNode
:{
tag: "div",
children: [
{
text: "Hello"
}
]
}
可能对应如下
DOM
操作:const node = document.createElement(VNode.tag);
node.textConent = 'Hello';
contanerDOM.appendChild(node);
更新则需要对比更新前后
VNode
,对变化部分执行DOM
操作。比如,以上
VNode
如果变为:{
tag: "div",
children: [
{
// text改变
text: "world"
}
]
}
则最终执行:
node.textContent = 'world';
VUE
的首次渲染对应mount
模块,更新对应patch
模块。所以,
render函数
执行后返回VNode
,根据情况不同,会走mount
或patch
的渲染逻辑:文章图片
如果想深入那么是谁在什么时机调用了虚拟DOM
相关知识,推荐阅读 snabbdom源码。这是个优秀的虚拟DOM库,VUE2
的虚拟DOM
部分就是fork
这个库改造的。
render函数
呢?响应式更新 在
VUE
中,状态变化会实时反映到视图上,比如:{{count}}
点击
div
后:- 触发点击事件,
count
变化 count
变化触发回调,回调中更新视图
文章图片
所以只需要建立
count
变化到执行render函数
的联系即可。具体来说,我们希望实现
reactive
及watchEffect
:// 定义状态
const state = reactive({count: 0});
// 监听状态变化
watchEffect(() => {
console.log(state.count);
})// 改变状态
state.count++;
reactive
定义状态。watchEffect
根据回调执行的情况决定监听哪些状态。比如
watchEffect
回调执行了console.log(state.count);
,他就会监听state
的变化。当执行
state.count++;
,由于watchEffect
监听了state
的变化,则其回调会触发,打印state.count
。这就是
Reactivity
模块。文章图片
VUE官方推出了
VUE3响应式原理课程讲解
Reactivity
的实现,这是B站链接。如果经济允许,请支持
正版
当实现了Reactivity
模块,我们就能将组件状态与后续流程串联起来。刚才讲过,
render函数
是编译器根据模版语法生成的。在面对带状态的模版语法时,比如上文的count
:{{count}}
render函数
内的count
是响应式的(即:count
实际是reactive({count: 0})
)。那么就能用
watchEffect
监听count
的变化。所以,在应用初始化时,会有类似逻辑:
let isMounted = false;
let oldVNode;
watchEffect(() => {
if (!isMounted) {
// mount逻辑
// 调用render函数
oldVNode = component.render();
// mount
mount(oldVNode);
} else {
// patch逻辑
// 调用render函数
newVNode = component.render();
patch(oldVNode, newVNode);
oldVNode = newVNode;
}
})
其中
component.render()
(render函数的执行)达到上文监听状态变化的效果:// 监听状态变化
watchEffect(() => {
console.log(state.count);
})
所以,该组件内任何状态变化都会触发
watchEffect
的执行,watchEffect
回调内会触发后续流程。文章图片
总结
VUE3
按原理大体可以划分为:- mount
- patch
- 编译器
- Reactivity
VUE
官方推出了实现简易VUE3教程,感兴趣的朋友可以去看看。如果有能力,记得去支持正版哦。