2023-03-13 10:40:08 +08:00

228 lines
8.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 前端框架的分类
> 面试题:现代前端框架不仅仅是 React、Vue还出现了像 Svelte、Solid.js 之类的框架,你觉得这些新框架相比 React、Vue 有什么样的区别?
## 自变量和因变量
现代前端框架,有一个非常重要的特点,那就是基于状态的声明式渲染。如果要概括的话,可以使用一个公式:
> UI = fstate
- state当前视图的一个状态
- f框架内部的一个运行机制
- UI宿主环境的视图描述
这里和初中的一个数学代数知识非常相似:
```js
2x + 1 = y
```
x 的变化会导致 y 的变化x 就被称之为自变量y 就被称之为因变量。类比上面 UI 的公式state 就是自变量state 的变化会导致最终计算出来的 UI 发生变化UI 在这里就是因变量。
目前在 React 中有很多 Hook例如
```js
const [x, setX] = useState(0);
```
比如上面的代码,我们就是定义了一个自变量
```jsx
function App(){
const [x, setX] = useState(0);
return <div onClick={()=>setX(x+1)}>{x}</div>
}
```
上面的 useState 这个 hook 可以看作是定义了一个自变量,自变量一变化,就会到导致依赖它的因变量发生变化,在上面的例子中,返回的 jsx 所描述的 UI 就是因变量。
因变量又可以分为两类:
- 没有副作用的因变量
- 有副作用的因变量
**没有副作用的因变量**
在 React 中useMemo 就是定义一个没有副作用的因变量
```js
const y = useMemo(() => x * 2 + 1, [x]);
```
在上面的代码中,我们使用 useMemo 定义了一个没有副作用的因变量 yy 的值取决于 x 的值x 的值一变化y 的值也会跟着变化
**有副作用的因变量**
在 React 中,可以使用 useEffect 来定义一个有副作用的因变量
```js
useEffect(() => document.title = x, [x]);
```
上面的代码依赖于自变量 x 的变化,当 x 发生变化的时候,会修改页面的标题,这就是一个副作用操作。
那么接下来,我们来总结一下:自变量的变化,会导致三种情况的因变量发生改变:
- 自变量的变化,导致 UI 因变量变化
```js
function Counter(){
const [num, setNum] = useState(0);
return (
<div onClick={()=>setNum(num+1)}>{num}</div>
);
}
```
- 自变量的变化,导致无副作用的因变量发生变化
```js
function Counter(){
const [num, setNum] = useState(0);
const fiexedNum = useMemo(()=>num.toFiexed(2), [num]);
return (
<div onClick={()=>setNum(num+1)}>{fiexedNum}</div>
);
}
```
- 自变量的变化,导致有副作用的因变量发生变化
```js
function Counter(){
const [num, setNum] = useState(0);
useEffect(()=>document.title=num, [num]);
return (
<div onClick={()=>setNum(num+1)}>{num}</div>
);
}
```
## 框架的分类
上面我们介绍了自变量和因变量state 实际上就是自变量,自变量的变化直接或者间接的改变了 UI上面的公式实际上还可以分为两个步骤
- 根据自变量 state 计算出 UI 的变化
- 根据 UI 的变化执行具体的宿主环境的 API
以前端工程师最熟悉的浏览器为例,那么第二个步骤就是执行 DOM 相关 API对于这个步骤来讲不同的框架实际上实现基本是相同的这个步骤不能作为框架分类的依据差别主要体现在步骤一上面这个步骤一也是针对目前各大框架的一个分类的依据。
接下来我们来看一个应用的示例:
该应用由三个组件组成
<img src="https://xiejie-typora.oss-cn-chengdu.aliyuncs.com/2023-02-22-081811.png" alt="image-20230222161811030" style="zoom:50%;" />
A 组件是整个应用的根组件,在这个根组件中,有一个自变量 aa 的变化会导致 UI 的重新渲染。
<img src="https://xiejie-typora.oss-cn-chengdu.aliyuncs.com/2023-02-22-082329.png" alt="image-20230222162329389" style="zoom:50%;" />
上图表示在 A 组件中引入了一个因变量 bA 组件中的自变量 a 的改变会导致因变量 b 的改变,而这个因变量 b 又作为 props 传递到了子组件 B 当中。
B 组件中也有一个自变量 c在该组件中还接收从父组件 A 传递过来的 props b最终在 UI 中渲染 b + c
<img src="https://xiejie-typora.oss-cn-chengdu.aliyuncs.com/2023-02-22-083204.png" alt="image-20230222163203653" style="zoom:50%;" />
在组件 C 中,接收从根组件 A 传递过来的数据 a从而 a 变成 C 组件的一个自变量。
接下来我们来总结一下,各个组件中所包含的自变量:
- A 组件
- 自变量 a
- a 的因变量 b
- B 组件
- 从 A 组件传递过来的自变量 b
- 自变量 c
- C 组件
- 从 A 组件传递过来的自变量 a
理清楚自变量之后,我们就可以从三个维度去整理自变量和不同维度之间的关系。
**自变量与 UI 的对应关系**
从 UI 层面去考虑的话,自变量的变化会导致哪些 UI 发生变化?
- a 变化导致 A 的 UI 中的 {a} 变化
- a 变化导致因变量 b 变化,导致 B 的 UI 中的 {b+c} 变化
- a 变换导致 C 的 UI 中的 {a} 变化
- a 变化导致 C 的 UI 中的 {a.toFixed(2)} 变化
- c 变化导致 B 的 UI 中的 {b+c} 变化
总共我们梳理出来的 UI 变化路径有 5 条,接下来我们要做的事情就是根据梳理出来的变化路径执行具体的 DOM 操作即可。
**自变量与组件的对应关系**
从组件的层面去考虑的话,自变量的变化会导致哪些组件发生变化呢?
- a 变化导致 A 组件 UI 变化
- a 变化导致 b 变化,从而导致 B 组件的UI 变化
- a 变化导致组件 C 的UI 变化
- c 变化导致组件 B 的 UI 变化
相较于上面的自变量与 UI 的对应关系,当我们考虑自变量与组件之间的关系时,梳理出来的路径从 5 条变成了 4 条。虽然路径减少了,但是在运行的时候,需要进行额外的操作,就是确定某一个组件发生变化时,组件内部的 UI 需要发生变化的部分。例如,通过路径 4 只能明确 B 组件发生了变化,但是具体发生了什么变化,还需要组件内部进行进一步的确定。
**自变量与应用的对应关系**
最后我们考虑自变量和应用之间的关系,那么路径就变成了:
- a 变化导致应用中发生 UI 变化
- c 变化导致应用中发生 UI 变化
整体路径从 4 条减少为了 2 条,虽然路径减少了,但是要做的额外的工作更多了。比如 a 的变化会导致应用中的 UI 发生变化,那么究竟是哪一部分的 UI ?这些需要额外的进行确定。
最后我们可以总结一下,前端框架需要关注自变量和 xUI、组件、应用 的对应关系,随着 x 的抽象层级不断下降,自变量到 UI 变化的路径条数就会增多。路径越多,则意味着前端框架在运行时消耗在“寻找自变量与 UI 对应关系”上面的时间越少。
根据上面的特点,我们就可以针对现代前端框架分为三大类:
- 元素级框架
- 组件级框架
- 应用级框架
以常见的前端框架为例React 属于应用级框架Vue 属于组件级的框架,而新的 Svelte、Solid.js 属于元素级框架。
## 真题解答
>题目:现代前端框架不仅仅是 React、Vue还出现了像 Svelte、Solid.js 之类的框架,你觉得这些新框架相比 React、Vue 有什么样的区别?
>
>参考答案:
>
>所有的现代前端框架,都有一个非常重要的特点,那就是“基于状态的声明式渲染”。概括成一个公式的话,那就是 UI = fstate
>
>这里有一点类似于初中数学中自变量与因变量之间的关系。例如在上面的公式中state 就是一个自变量state 的变化会导致 UI 这个因变量发生变化。
>
>不同的框架在根据自变量state的变化计算出 UI 的变化这一步骤有所区别,自变量和 x应用、组件、UI的对应关系随着 x 抽象的层级不断下降,“自变量到 UI 变化”的路径则不断增多。路径越多,则意味着前端框架在运行时消耗在寻找“自变量与 UI 的对应关系”上的时间越少。
>
>以“与自变量建立对应关系的抽象层级”可以作为其分类的依据,按照这个标准,前端框架可以分为以下三类:
>
>- 元素级框架
>- 组件级框架
>- 应用级框架
>
>以常见的前端框架为例React 属于应用级框架Vue 属于组件级框架Svelte、Solid.js 属于元素级框架。