likes
comments
collection
share

浅谈前端框架

作者站长头像
站长
· 阅读数 17

我正在参加「掘金·启航计划」

以抽象层级角度给前端框架分类

我们把前端框架用一个公式来概括:UI=f(state)

  • UI代表视图,在浏览器中就是我们所见到的网页
  • state代表当前视图的状态,我们称之为自变量
  • f代表框架内部运行机制,也就是框架做了什么

通过上述公式我们知道自变量变化会导致UI的变化,而自变量在框架中的定位不同也会造成自变量到UI变化的路径不同,例如这段代码:

//组件A
<div>
<h1>{a}</h1>
<B a={a} />
</div>

//组件B
<div>
<span>{b}</span>
<a>{a+b}</a>
</div>

以元素角度来说:(以下变化都值UI的变化)

  • a变化会导致A中{a}变化
  • a变化会导致B中{a+b}变化
  • b变化会导致B中{b}变化
  • b变化会导致B中{a+b}变化

以组件角度来说:

  • a变化会导致A变化
  • a变化会导致B变化
  • b变化会导致B变化

以应用角度来说:

  • a变化会导致应用变化
  • b变化会导致应用变化

我们把自变量在不同框架中的对应关系称为x,随着x的抽象层级不断下降(应用->组件->UI),”自变量到UI变化“的路径增多。路径越多,意味着前端框架在运行时消耗在寻找”自变量与UI的对应关系“上的时间越少

所以,前端框架中”与自变量建立对应关系的抽象层级“可以作为其分类依据。按照这个标准,前端框架可以分为以下三类:

  • 应用级框架
  • 组件级框架
  • 元素级框架

React属于应用级框架,Vue属于组件级框架,Solid.js属于元素级框架

React被称为应用级框架的原因在于,其每次更新流程都是从应用的根节点开始,遍历整个应用,对比其他框架:

  • Vue3的更新流程开始于组件
  • Svelte的更新流程开始于元素

基于这样的实现原理,React甚至不需要确定哪个自变量发生了变化。由于任何自变量的变化都会开启一次遍历应用的更新流程,因此React不需要“细粒度更新”和AOT

总结:前端框架需要关注”与自变量建立对应关系的抽象层级“。

每次更新都遍历应用,那性能会不会很差?

答案是不会,有两方面的原因。一方面,React 内部有优化机制。另一方面,React为开发者提供了相关 API用于“减少无意义的遍历过程”,比如 shouldComponentUpdate、React.memo、PureComponent。

为什么 Vue中不存在这些性能优化APl 呢?

显然,组件级别框架的定位和AOT优化已经减少了大部分无意义的遍历过程。可以说,由于 React 没有完成这部分性能优化的任务,因此这部分工作交到了开发者手中。

举例:

React中对元素绑定的事件进行了事件代理,把所以子元素的事件通过代理的方式绑定到了更元素上面,在通过e.target获取触发事件的元素

而Vue则不需要,因为它的虚拟DOM和真实DOM是一一对应的

实现简易“细粒度更新”版本的React Hooks:github.com/shiqifriend…

相比React Hooks有两个优点:

  • 无须显示指明依赖
  • 由于可以自动追踪依赖,因此不受React Hooks”不能在条件语句中声明Hooks“的限制

为什么React Hooks,没有使用细粒度更新呢?

原因在于React属于应用级框架,从关注”自变量与应用的对应关系“角度看,其更新粒度不需要很细,因此无须使用细粒度更新。作为代价,React Hooks在使用上则会受到与上述两个优点相对应的两种限制