大家好,我是卡颂。
都说中国人考究中庸之道,中国人造的框架考究么?
本文会从原理层面解说 Vue
是如何在运行时与编译时之间放弃中庸的均衡。
UI = fn(state)
简直所有前端框架工作原理都能用如下公式概括:
UI = fn(state)
UI
(视图)能够通过 state
(状态)通过fn
(框架) 计算得出。
然而具体原理上,框架之间却千差万别。
能够依照 更新粒度 将他们分为三类:
- 树级更新
- 组件级更新
- 节点级更新
更新粒度没有优劣之分,只是对应不同的实现
接下来咱们简略理解下不同粒度更新形式的实现原理。
假如有如下组件树,其中 Cpn
是一个自定义组件,内部结构为ul>li*2
:
咱们心愿将 Cpn
内的一个 li
更新为黄色:
树级更新
树级更新 的框架会再生成一棵残缺 虚构 DOM 树 ,生成过程中与之前的 虚构 DOM 树 对应节点进行比拟:
找到变动的节点后,执行对应 DOM
操作。
树级更新 框架的特点是:
- 依赖 虚构 DOM
- 不关怀触发更新的节点(因为会通过 虚构 DOM的全树比照找到他)
采纳这种更新形式最有名的框架就是React
。
组件级更新
下面的例子,如果是 组件级更新 框架。
会找到触发更新节点所在组件,生成该组件的 虚构 DOM 树 (而不是全树的 虚构 DOM 树 ),生成过程中与该组件之前的 虚构 DOM 树 对应节点进行比拟:
找到变动的节点后,执行对应 DOM
操作。
组件级更新 框架的特点是:
- 依赖 虚构 DOM
- 关怀触发更新的节点(虚构 DOM的比照会作用于该节点所在组件)
采纳这种更新形式最有名的框架就是Vue
。
节点级更新
如果是 节点级更新 框架,在编译时会依据 状态变动对应的 DOM 变动 间接生成对应办法,当状态扭转后间接调用对应办法。
下面的例子,在编译时会关联 color
状态与 changeColor
办法:
function changeColor(newColor) {li.style.color = newColor;}
当扭转 color
状态后间接调用 changeColor
办法更新 li
对应DOM
。
节点级更新 框架的特点是:
- 不依赖 虚构 DOM,依赖预编译(建设状态与扭转
DOM
的办法之间的分割) - 关怀触发更新的节点(节点状态与更新办法一一对应)
采纳这种更新形式最有名的框架就是Svelte
。
中庸的 Vue3
Vue
作为 组件级更新 代表,更新粒度介于 树级 与节点级 之间。那到底是两头偏左呢,还是两头偏右呢?
Vue3
说:
我要重复横跳,两边我都要
Vue3
中蕴含三种树状构造:
形容视图的树 -> 虚构 DOM 树 -> 实在 DOM 树
其中 形容视图的树 官网举荐应用 模版语法,但也能应用JSX
。
不论是哪种形式,最终都会转化为 虚构 DOM 树。
当应用 JSX
时,Vue3
领有了 React
运行时的灵活性,此时的 Vue3
能够看作是 加强版 React + Mobx
当应用 模版语法 ,Vue3
引入了 预编译 技术。此时能够将 Vue3
的工作流程细化为四步:
形容视图的树 -> VNode 树 -> Block 数组 -> 实在 DOM 树
其中 VNode 树
就是惯例意义的 虚构 DOM 树 ,Block 数组
则为 VNode 树 中对状态有依赖,会变动的那局部 VNode
组成的数组。
比方,对于如下模版语法:
<template>
<section>
<div>i am</div>
<p>{{name}}</p>
</section>
</template>
section
与 div
不蕴含状态,不会变动,所以会转化为VNode
,然而没有对应Block
。
p
蕴含状态 name
,会转化为VNode
与Block
。
当该 template
所在组件触发 name
状态变动,之前须要顺次创立 section
、div
、p
的VNode
并进行比拟。
有了预编译技术后只须要遍历 Block 数组
进行比拟。
用上文的例子即只须要比照一个 li
节点:
在这种状况下,尽管是应用 虚构 DOM的 组件级更新 框架,然而曾经很靠近 节点级更新 框架了。
总结
本文按更新粒度介绍了三种不同类型的框架,以及 Vue3
在抉择 JSX
与模版语法
时在灵活性与更新粒度间的灵便变动。
能够说是很合乎中庸之道了。
有人会问,应用 Vue3
的用户大部分都能承受 模版语法 ,为什么不间接摈弃 虚构 DOM,应用 预编译技术 ,实现真正的 节点级更新?
一方面,虚构 DOM使框架脱离具体的视图层,更不便跨端渲染。
另一方面,Vue2
社区生态积攒了大量基于 虚构 DOM的库。
如果是你,在这种状况下会作何抉择呢?