We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
前段时间,StackOverflow发布了2021调查报告,Svelte作为一个非主流框架,技压React、Vue等众多前端框架,成为了web领域最受欢迎的框架,你听说过Svelte吗?
Svelte
React
Vue
从React15到17,再到即将到来的React18,再从Vue2到Vue3,会不会有种前端框架发展太快?学不动了的感觉?
那么我们来探讨一下,这些主流框架之间的区别吧
tips:本文借鉴了卡颂老师在B站发布的视频,本文发布已征得本人同意,点击查看原视频:『货很干』主流前端框架的实现原理,懂完了你
主流前端框架都遵循组件化的开发模式,具体来说,框架开发的应用分为三级抽象:
应用 => 组件 => 节点
就拿掘金App举例来说,掘金是一个应用,这个应用由header组件、导航栏组件、列表组件、footer组件四个部分构成,而这些组件还能继续拆分,比如列表组件由多个列表项组件构成,导航栏组件由多个导航组件构成,导航组件内部,由描述视图的节点加上业务逻辑构成。
header组件
导航栏组件
列表组件
footer组件
列表项组件
导航组件
节点
业务逻辑
<ul>
<li>
总结一下:框架中最小的单位是节点,节点加业务逻辑构成组件,多个组件构成应用,这就是前端框架的抽象层级划分。
那么前端框架的工作原理是什么呢?我们可以用一个公式概括:UI = F(state)
UI = F(state)
总结起来就是:框架内部的运行机制根据状态渲染视图
运行机制
状态
视图
说到这里大家可能会有疑惑,既然主流前端框架的工作原理都是一样的,那它们有什么区别呢?
答案是:更新粒度的区别
刚才讲过,框架有三级抽象:应用、组件、节点,同样的,主流前端框架也分为三种更新粒度,应用级,组件级,节点级,接下来我们看看这些框架内部都由哪些技术构成:
应用
组件
应用级
组件级
节点级
我们从最细的粒度,节点级更新的框架Svelte开始讲起(如果想了解这个框架,可以点击这里查看官网)
首先定义一个计数器组件,先定义组件逻辑:
count
handleClick
<button>
<p>
经过渲染,视图上的数字初始值为0,每次点击都会加1
状态变化
节点变化
具体方法
对应视图
在我们上面的例子中:
变量count变化可能导致<button>节点中的文本节点发生变化,由于<p>节点不包含状态变化,所以它不会出现在编译后的update方法中(这种将状态变化可能导致的节点变化编译为具体方法的技术,被称为预编译,网站中实际运行的代码,都是预编译之后的代码)
预编译
监听状态变化,具体方案是采用了发布订阅设计模式,当创建一个状态后,会为状态维护一张订阅了该状态变化的表,所有需要监听变化的回调函数都在表中进行了注册,这就是发布订阅中的订阅部分
发布订阅
订阅了该状态变化
监听变化
注册
订阅
每当状态变化,会发布这张表,将状态变了这一消息发布出去,每个订阅该状态变化的回调函数都会收到通知并执行,这就是发布订阅中发布的部分
发布
状态变了
订阅该状态变化的回调函数
通过以上这种方式,框架能对每个状态化做出反应,这种精确到状态的更新被称为细粒度更新,这也就是节点级更新框架的工作原理。
细粒度更新
讨论到应用级更新框架,这种框架会采用虚拟DOM的技术,我们通过 React 来举例,首先,我们用 React 重写刚才的 Counter 组件:
import React, { useState } from 'react'; const Counter: React.FC = () => { const [count, setCount] = useState<number>(0); const handleClick = () => setCount(count + 1); return <button onClick={handleClick}>{count}</button>; }; export default () => ( <> <Counter /> <Counter /> </> );
在父组件内使用两个 <Counter /> 子组件,这两个 Counter 子组件可以独立计数
<Counter />
首屏渲染时,React会根据应用的树结构,生成一颗对应的虚拟DOM树
虚拟DOM树
每个节点
同级节点
button
虚拟DOM
刚才讲过,节点级更新的框架需要监听状态的变化,与节点级框架不同,应用级框架不关心是哪个状态发生了变化,应用中的任何组件中的任何一个状态变化,都会从root根节点创建一颗完整的虚拟DOM树,然后通过前后两棵虚拟DOM树的比较,找到变化的部分,最终将变化的部分更新到视图,主流的应用级更新框架就是React
根节点
你可能会问:为什么状态变化后,要生成一颗完整的虚拟DOM树,而不是只为改变的状态对应的组件生成对应的虚拟DOM树?这样一来,就能节省很多虚拟DOM操作的开销,从而降低内存的开销,达到性能优化的目的
完整的虚拟DOM树
对应的组件
对应的虚拟DOM树
作为组件级更新框架的代表,Vue2采用虚拟DOM + 细粒度更新实现,Vue3则在此基础上引入了预编译,并升级了细粒度更新的实现。
最后总结一下:主流前端框架的工作原理是 框架的运行机制根据状态渲染视图,他们的区别是更新粒度不同,三种更新粒度的框架分别对应不同的技术点:
The text was updated successfully, but these errors were encountered:
No branches or pull requests
前言
前段时间,StackOverflow发布了2021调查报告,
Svelte
作为一个非主流框架,技压React
、Vue
等众多前端框架,成为了web领域最受欢迎的框架,你听说过Svelte
吗?从React15到17,再到即将到来的React18,再从Vue2到Vue3,会不会有种前端框架发展太快?学不动了的感觉?
那么我们来探讨一下,这些主流框架之间的区别吧
tips:本文借鉴了卡颂老师在B站发布的视频,本文发布已征得本人同意,点击查看原视频:『货很干』主流前端框架的实现原理,懂完了你
组件化
主流前端框架都遵循组件化的开发模式,具体来说,框架开发的应用分为三级抽象:
应用 => 组件 => 节点
就拿掘金App举例来说,掘金是一个应用,这个应用由
header组件
、导航栏组件
、列表组件
、footer组件
四个部分构成,而这些组件还能继续拆分,比如列表组件
由多个列表项组件
构成,导航栏组件
由多个导航组件
构成,导航组件内部,由描述视图的节点
加上业务逻辑
构成。<ul>
标签包裹的<li>
节点<li>
节点时,需要跳转到对应的地方,并且更新列表组件
中的数据总结一下:框架中最小的单位是节点,节点加业务逻辑构成组件,多个组件构成应用,这就是前端框架的抽象层级划分。
那么前端框架的工作原理是什么呢?我们可以用一个公式概括:
UI = F(state)
总结起来就是:框架内部的
运行机制
根据状态
渲染视图
说到这里大家可能会有疑惑,既然主流前端框架的工作原理都是一样的,那它们有什么区别呢?
答案是:更新粒度的区别
刚才讲过,框架有三级抽象:
应用
、组件
、节点
,同样的,主流前端框架也分为三种更新粒度,应用级
,组件级
,节点级
,接下来我们看看这些框架内部都由哪些技术构成:节点级更新框架:Svelte
我们从最细的粒度,节点级更新的框架Svelte开始讲起(如果想了解这个框架,可以点击这里查看官网)
首先定义一个计数器组件,先定义组件逻辑:
count
,初始值为0handleClick
,每次点击时count + 1<button>
节点,将点击事件绑定为<button>
节点的点击回调函数<p>
节点,内容为一段文本经过渲染,视图上的数字初始值为0,每次点击都会加1
节点级更新框架的原理分为三步:
状态变化
可能导致的节点变化
编译为具体方法
状态变化
状态变化
后,直接调用具体方法,改变对应视图
在我们上面的例子中:
变量
count
变化可能导致<button>
节点中的文本节点发生变化,由于<p>
节点不包含状态变化,所以它不会出现在编译后的update方法中(这种将状态变化可能导致的节点变化编译为具体方法的技术,被称为预编译
,网站中实际运行的代码,都是预编译
之后的代码)监听状态变化,具体方案是采用了
发布订阅
设计模式,当创建一个状态后,会为状态维护一张订阅了该状态变化
的表,所有需要监听变化
的回调函数都在表中进行了注册
,这就是发布订阅中的订阅
部分每当状态变化,会
发布
这张表,将状态变了
这一消息发布出去,每个订阅该状态变化的回调函数
都会收到通知并执行,这就是发布订阅中发布
的部分通过以上这种方式,框架能对每个状态化做出反应,这种精确到状态的更新被称为
细粒度更新
,这也就是节点级更新框架的工作原理。应用级更新框架:React
讨论到应用级更新框架,这种框架会采用虚拟DOM的技术,我们通过
React
来举例,首先,我们用 React 重写刚才的 Counter 组件:在父组件内使用两个
<Counter />
子组件,这两个 Counter 子组件可以独立计数首屏渲染时,React会根据应用的树结构,生成一颗对应的
虚拟DOM树
<button>
节点后,调用handleClick
,触发状态更新,react会重新生成一颗完整的虚拟DOM树每个节点
会与之前的虚拟DOM树的同级节点
进行比较,如果存在差异,记录该差异<Counter />
组件的<button>
节点时,发现前后两个button
节点的内容不一致,就会记录下来,等新的虚拟DOM
生成完毕后,将记录的差别统一渲染到视图上总结
刚才讲过,
节点级
更新的框架需要监听状态
的变化,与节点级
框架不同,应用级
框架不关心是哪个状态发生了变化,应用中的任何组件中的任何一个状态变化,都会从root根节点
创建一颗完整的虚拟DOM树
,然后通过前后两棵虚拟DOM树
的比较,找到变化的部分,最终将变化的部分更新到视图,主流的应用级更新框架就是React
提问
你可能会问:为什么状态变化后,要生成一颗
完整的虚拟DOM树
,而不是只为改变的状态对应的组件
生成对应的虚拟DOM树
?这样一来,就能节省很多虚拟DOM操作的开销,从而降低内存的开销,达到性能优化的目的组件级更新框架:Vue
作为组件级更新框架的代表,Vue2采用虚拟DOM + 细粒度更新实现,Vue3则在此基础上引入了预编译,并升级了细粒度更新的实现。
复习一下吧
最后总结一下:主流前端框架的工作原理是 框架的
运行机制
根据状态
渲染视图
,他们的区别是更新粒度不同,三种更新粒度的框架分别对应不同的技术点:The text was updated successfully, but these errors were encountered: