大家好,我是凯森。最近中午没什么胃口,就找了一个VUE源码相关的视频来呈现一个饭剧。人吃几顿饭就长胖,VUE也明白。本文为大家带来VUE3原理快速指南。模块划分如果我们使用VUE的模板语法来定义:
hello
最后,VUE会帮我们在浏览器中渲染对应的DOM节点。这个节点的描述会发生4次变化,跨越编译时和运行时:模板语法会在编译时被编译器转换成render函数,类似于:render(h){returnh('div','hello');}在运行时,render函数执行后返回的h函数的执行结果为VNode(即虚拟DOM),类似:{tag:"div",children:[{text:"Hello"}]}最后VUE根据VNode的信息在浏览器中渲染对应的DOM。那么,谁在推动这个过程?mount和patch组件有两种不同的渲染逻辑:firstrender和update。第一次渲染的意思是从头开始,比如上面的VNode:{tag:"div",children:[{text:"Hello"}]}可能对应如下DOM操作:constnode=document.createElement(VNode.tag);node.textConent='Hello';contanerDOM.appendChild(node);Update需要比较更新前后的VNode,对变化的部分进行DOM操作。比如上面的VNode变成:{tag:"div",children:[{//textchangestotext:"world"}]},那么最后执行:node.textContent='world';VUE的第一次渲染对应挂载模块,更新对应的补丁模块。因此,render函数执行完毕后,返回到VNode。根据不同的情况,会使用mount或者patch的渲染逻辑:如果想深入了解虚拟DOM,推荐阅读snabbdom的源码。这是一个优秀的虚拟DOM库。VUE2的虚拟DOM部分由fork库改造而来。那么谁在什么时候调用了render函数呢?响应式更新在VUE中,状态变化会实时反映到视图上,例如:{{count}}
点击div后:触发click事件,并计数变化触发回调,视图在回调中更新。现在我们已经知道第二步是因为触发了下面的流程:所以我们只需要建立count变化和render函数执行之间的联系即可。具体来说,我们要实现reactive和watchEffect://定义状态conststate=reactive({count:0});//监控状态变化watchEffect(()=>{console.log(state.count);})//改变状态state.count++;reactive定义状态。watchEffect根据回调的执行情况来决定监听哪些状态。例如,如果watchEffect回调执行console.log(state.count);,它将监视状态变化。当state.count++;被执行时,由于watchEffect监听状态变化,它的回调将被触发并打印state.count。这是反应模块。VUE官方推出VUE3ResponsivePrinciples课程,讲解Reactivity的实现。这是B站链接,如果经济允许,请支持正版。当Reactivity模块实现后,我们就可以将组件状态与后续流程联系起来。如前所述,渲染函数是由编译器根据模板语法生成的。面对带有状态的模板语法,比如上面的count:{计数:0}))。然后就可以使用watchEffect来监听count的变化了。因此,在应用初始化的时候,会有类似的逻辑:letisMounted=false;letoldVNode;watchEffect(()=>{if(!isMounted){//挂载逻辑//调用渲染函数oldVNode=component.render();//mountmount(oldVNode);}else{//补丁逻辑//调用渲染函数newVNode=component.render();patch(oldVNode,newVNode);oldVNode=newVNode;}})wherecomponent.render()(renderFunctionexecution)实现上面监听状态变化的效果://监听状态变化watchEffect(()=>{console.log(state.count);})因此,这个组件的任何状态变化都会触发watchEffect的执行,后续流程会在watchEffect回调中触发。总结一下,VUE3按照原理大致可以分为三类:mountpatch编译器ReactivityVUE官方推出了一个简单的VUE3教程,有兴趣的朋友可以去看看。有能力的记得支持原版。欢迎加入人类优质前端框架群,与大家一起成长