大家好,我是卡颂。

最近中午没胃口,找来VUE源码相干视频来当下饭剧。几顿饭上来,人胖了,VUE也整明确了。

这篇文章为你带来一份VUE3原理速成指南。

模块划分

如果咱们用VUE的模版语法定义:

<div>hello</div>

最终VUE会帮咱们在浏览器中渲染对应的DOM节点

这之间对这段节点的形容会经验4次变动,横跨编译时运行时

模版语法在编译时会被编译器转化为render函数,相似:

render(h) {  return h('div', 'hello');}

在运行时,render函数执行后返回的h函数的执行后果就是VNode(也就是虚构DOM),相似:

{  tag: "div",  children: [    {      text: "Hello"    }  ]}

最终,VUE依据VNode的信息,在浏览器渲染对应DOM

那么,是谁在驱动这一流程?

mount和patch

组件有两种不同的渲染逻辑:首次渲染更新

首次渲染意味着从无到有,比方上文的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的渲染逻辑:

如果想深刻虚构DOM相干常识,举荐浏览snabbdom源码。这是个优良的虚构DOM库,VUE2虚构DOM局部就是fork这个库革新的。

那么是谁在什么机会调用了render函数呢?

响应式更新

VUE中,状态变动会实时反映到视图上,比方:

<div @click="count++">{{count}}</div>

点击div后:

  1. 触发点击事件,count变动
  2. count变动触发回调,回调中更新视图

以后咱们曾经晓得第二步是因为触发了如下流程:

所以只须要建设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模块。

VUE官网推出了VUE3响应式原理课程解说Reactivity的实现,这是B站链接。如果经济容许,请反对正版

当实现了Reactivity模块,咱们就能将组件状态与后续流程串联起来。

方才讲过,render函数是编译器依据模版语法生成的。在面对带状态的模版语法时,比方上文的count

<div @click="count++">{{count}}</div>

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教程,感兴趣的敌人能够去看看。如果有能力,记得去反对正版哦。