中国人中庸之道,中国人造的框架呢?

开发 前端
本文按更新粒度介绍了三种不同类型的框架,以及Vue3在选择JSX与模版语法时在灵活性与更新粒度间的灵活变化。

[[412125]]

大家好,我是卡颂。

都说中国人讲究中庸之道,中国人造的框架讲究么?

本文会从原理层面讲解Vue是如何在运行时与编译时之间保持中庸的平衡。

UI = fn(state)

几乎所有前端框架工作原理都能用如下公式概括:

  1. 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方法:

  1. function changeColor(newColor) { 
  2.   li.style.color = newColor; 

当改变color状态后直接调用changeColor方法更新li对应DOM。

「节点级更新」框架的特点是:

  • 不依赖「虚拟DOM」,依赖预编译(建立状态与改变DOM的方法之间的联系)
  • 关心触发更新的节点(节点状态与更新方法一一对应)

采用这种更新方式最有名的框架就是Svelte。

中庸的Vue3

Vue作为「组件级更新」代表,更新粒度介于「树级」与「节点级」之间。那到底是中间偏左呢,还是中间偏右呢?

Vue3说:

我要反复横跳,两边我都要

Vue3中包含三种树状结构:

  1. 描述视图的树 -> 虚拟DOM树 -> 真实DOM树 

其中「描述视图的树」官方推荐使用「模版语法」,但也能使用JSX。

不管是哪种方式,最终都会转化为「虚拟DOM树」。

当使用JSX时,Vue3拥有了React运行时的灵活性,此时的Vue3可以看作是「加强版React + Mobx」

当使用「模版语法」,Vue3引入了「预编译」技术。此时可以将Vue3的工作流程细化为四步:

  1. 描述视图的树 -> VNode树 -> Block数组 -> 真实DOM树 

其中VNode树就是常规意义的「虚拟DOM树」,Block数组则为「VNode树」中对状态有依赖,会变化的那部分VNode组成的数组。

比如,对于如下模版语法:

  1. <template> 
  2.   <section
  3.     <div>i am</div> 
  4.     <p>{{name}}</p> 
  5.   </section
  6. </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」的库。

如果是你,在这种情况下会作何选择呢?

 

责任编辑:姜华 来源: 魔术师卡颂
相关推荐

2009-01-03 08:41:16

中国上网

2012-10-11 20:10:41

无线路由无线产品飞鱼星科技

2016-11-22 11:15:00

IT老年人

2019-07-18 10:49:15

GitHub软件代码

2022-07-12 22:10:34

人工智能AI

2016-08-08 12:51:17

操作系统Linux中兴新支点操作系统

2021-02-07 09:07:24

程序员码农代码

2015-08-06 10:59:35

2022-07-27 13:19:26

人工智能AI

2015-06-26 11:48:31

2010-03-16 20:03:19

VPN技术中国人寿深信服科技

2018-02-28 16:51:47

春节大数据在移动支付

2018-01-18 22:12:14

2013-12-02 15:42:42

华为中国人寿

2009-01-15 09:07:03

北电破产吴振生

2014-04-09 13:24:11

锐捷网络人才培养

2019-03-29 15:31:10

2024-11-04 08:01:19

Node.js底层分词
点赞
收藏

51CTO技术栈公众号