大概几集下饭剧时间就能懂的VUE3原理

大家好,我是卡颂。
最近中午没胃口,找来VUE源码相关视频来当下饭剧。几顿饭下去,人胖了,VUE也整明白了。
大概几集下饭剧时间就能懂的VUE3原理
文章图片

这篇文章为你带来一份VUE3原理速成指南。
模块划分 如果我们用VUE的模版语法定义:

hello

最终VUE会帮我们在浏览器中渲染对应的DOM节点
这之间对这段节点的描述会经历4次变化,横跨编译时与运行时:
大概几集下饭剧时间就能懂的VUE3原理
文章图片

模版语法在编译时会被编译器转化为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,根据情况不同,会走mountpatch的渲染逻辑:
大概几集下饭剧时间就能懂的VUE3原理
文章图片

如果想深入 虚拟DOM相关知识,推荐阅读 snabbdom源码。这是个优秀的虚拟DOM库, VUE2虚拟DOM部分就是 fork这个库改造的。
那么是谁在什么时机调用了render函数呢?
响应式更新 在VUE中,状态变化会实时反映到视图上,比如:
{{count}}

点击div后:
  1. 触发点击事件,count变化
  2. count变化触发回调,回调中更新视图
当前我们已经知道第二步是由于触发了如下流程:
大概几集下饭剧时间就能懂的VUE3原理
文章图片

所以只需要建立count变化到执行render函数的联系即可。
具体来说,我们希望实现reactivewatchEffect
// 定义状态 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模块。
大概几集下饭剧时间就能懂的VUE3原理
文章图片

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原理
文章图片

总结 VUE3按原理大体可以划分为:
  • mount
  • patch
  • 编译器
  • Reactivity
VUE官方推出了实现简易VUE3教程,感兴趣的朋友可以去看看。如果有能力,记得去支持正版哦。

    推荐阅读