乐趣区

关于前端:大概几集下饭剧时间就能懂的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 教程,感兴趣的敌人能够去看看。如果有能力,记得去反对正版哦。

退出移动版