关于前端:大概几集下饭剧时间就能懂的VUE3原理

大家好,我是卡颂。

最近中午没胃口,找来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教程,感兴趣的敌人能够去看看。如果有能力,记得去反对正版哦。

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理