Open BetaSu opened 2 years ago
纯运行时框架比较好理解,举一个例子 JQuery
.虽然 JQuery
并不能称之为框架,但我们可以看到 JQuery
的一些特点,不需要在 html 上做一些例如 v-show
v-bind
的标记,也不需要稀奇古怪的写法,也不需要什么特定的环境,引入一个 script 文件
即可,只是一个单纯的 js库
,优化了 js
与 Dom
之间的交互。同样的,在 React
身上我们也可看到许多共通点,React 在 js
层面上也没有许多稀奇古怪的写法,以 一切皆在 js 之下
为基准,也许这也是 React 自称一个 视图库
,而不把自己当成一个框架的原因。当然这一切都在不考虑 Jsx
的情况下,React
的运行时体现在与视图的交互比如 虚拟 dom
fiber
等。不使用 Jsx
手写 render 函数
虽然效果一样,但是尤为的繁琐,所以是在前端工程化的今天出现了编译。既然项目最后需要经过层层转译 tree-shake
UglifyJS.minify
打包生成,那我为什么不加一层转译让开发者的体验更好,React
将 render 函数
变为 Jsx语法糖
的形式出现,让诸多开发者的开发体验极大提升,React
还是一个纯运行时的库,Jsx
语法本质上依然还是 render 函数
,你写怎样的 Jsx
就会编译为怎样的 render 函数,同样的只要你想,你也可以无压力把 render 函数 反编译为 Jsx
这二者只不过在开发阶段展现给你的形式不一样,这样就可以引申出下一个 编译-运行时 框架 Vue
为什么称 Vue
为 编译-运行时 框架?因为 Vue
既可以当作一个纯运行时的视图库,同时又与编译分隔不开。如果你可以像使用 React 一样使用 Vue,你会发现 Vue
就是自动挡版本的 React ,你需要 setState 我只需要 state.value = ‘’ 直接触发视图更新,Vue 也使用了 render 函数,甚至你可以在 Vue
中使用 Jsx
,此时 Vue
可以保证 一切皆在 js 之下
,你把 Vue
当作一个单纯的 MVVM
的视图库就可以。那 Vue
的不可分隔的编译体现在哪?就是我们所熟知的 template ,为什么因为模板 Vue
被归类为 编译-运行时 框架,而 React 也有 Jsx
却仍然是 纯运行时框架。我们可以看两段代码。
// template
<div>
<h1 v-if="true" />
<h2 v-else />
</div>
// 编译后的render 函数 伪代码
// h('div', { children: true ? h('h1') : h('h2') })
<div>
{ true ? <h1 /> : <h2 /> }
</div>
// h('div', { children: true ? h('h1') : h('h2') })
可以看到其实二者的 render 函数其实可以保持一致,但是 jsx 只是将转换 Html 元素为 render 函数,而模板则将 if else 逻辑一同转换出来,再举一个例子
<div>{s ?? <h1 />}</div>
jsx 可以很轻松的转换为 h('div', { children: s ?? h('h1') }),如果在 vue 模板中就无法这样写,只能
<div>
<h1 v-if="s != null" />
</div>
// 转换出来的代码为 h('div', { children: s != null && h('h1') })
可以看到在使用模板的时候有许多限制,这也是为什么很多 React
开发者会说写 jsx
就像在写 js
,因为写 jsx
就是在写 js
。看到这里好似模板编译一无是处?那接下来就是编译发力的阶段。
既然我使用编译了,那就贯彻到底。虽然模板在 js 层面有很多限制,但是也得到了更多的能力,比如 Vue3
带来的性能改进,静态内容提升。还是上面的例子,对于 render 函数而言,jsx 只能原封不动的编译
<div>{true ? <h1 /> : <h2 />}</div>
// h('div', { children: true ? h('h1') : h('h2') })
这样想要重新生成虚拟 Dom 就需要层层调用 h 函数,但是模板可以可以做一些性能优化
;<div>
<h1 v-if="true" />
<h2 v-else />
</div>
const h1 = h('h1')
const h2 = h('h2')
// h('div', { children: true ? h1 : h2 })
这样再次生成 虚拟 Dom 的时候就节省两个函数执行的开销,还可以体现编译好处的就是 Vue
的指令,比如 v-show
这个指令,你可以想想在 React
中想要实现这个功能绝对没有直接写个 v-show
方便。此外你可以自定义指令,假设有个需求需要将权限控制细分到按钮,在 Vue
中你可以写一个 v-permission 指令,只需要加到 <button v-permission>
就可以,如果在 React
中可就要废一番脑细胞了。
Vue
使用编译的好处不仅体现在模板中,我们都知道 Vue
使用了单文件 .vue
的形式,这样也可以对 script
和 css
做优化,例如想要实现 css
隔离,只需要加一个简单的 scoped 就可以了,而 React
催生一大堆 css
方案,生态丰富是好事,但有时候想解决痛点只有一个就好了。在 Vue3
引入了 Composition Api ,Composition Api 在 js 下总有许多不舒服的地方,比如繁杂的 return 返回,ref 一个变量需要写繁琐的 .value
,而这些 Vue
也正在通过编译的方式解决 script-setup
。
对于纯编译框架 Svelte
了解的不多,只知道不需要虚拟 dom,通过编译对每个 Html
元素添加增删改方法,可以极细粒度的控制元素变更,轻运行时,性能很好。
,主要对比了 React
和 Vue
之间有关 运行时-编译时 之间的不同。其实你会发现虽然 Jsx
只是算做 React
生态的一部分,但也绕不开编译,只不过这个编译对 Js
能力几乎无影响。Vue 不使用模板也可以当作纯运行时的一个框架,但使用模板编译去拓展了很多能力。使用编译的初衷都是缘因对 Html-Js-Css
的不爽。render 函数
很烦,那我就创造一个 Jsx
,需要返回一大堆无用的东西,那我就开发 script-setup
。
二者之间的利弊其实挺明显的,纯运行时框架最大的利就是不会与 Js
有差异化,Js
能用的我都能用,尤其体现在生态方面,比如接入 Typescript
基本不需要什么 hack
方式。弊也很明显,能力只能局限在 Js
中,当性能出现瓶颈的时候,只能通过 Js
运行时的方式去解决,比如 fiber 并发模式。其实 Jsx
真的无法做编译时优化么?肯定是可以的,但是做了,也就不是一个纯粹的视图库了。
编译的利就是拓展了很多能力,觉得 Web 语法不爽,甚至可以搞一套自己喜欢的语法,只要最后编译为 Html-Js-Css
就可以了,但是弊就是要自己抹平与 Js 之间的差异,Vue
的 template
模板对 Typescript
支持也是老生常谈的问题,比如出现的新语法 ??
?.
这些想要在模板中使用都需要框架开发者主动去支持,如果没有人力及时支持怎么办?只能放弃使用或者自己发挥主观能动性。
Svelte
这种纯编译
的框架,因为在运行前直接编译生成HTML
代码而不是像reac
t和vue
这样生成vdom
转换为HTML
,因为少了在运行时候的转换所以减少了一些性能上的开销,但直接编译为HTML
也给Svelte
这种纯编译
的框架带来了最大的弊端,不灵活只能局限在浏览器以及支持HTML
格式的软件中使用,react
和vue
生成的是vdom
,大家都知道vdom就是描述元素状态的对象(例如:一个div的大小尺寸等),而vdom在不同环境中表现的形式不一样,正因为vdom的存在使得react
和vue
可以生成桌面端,移动端(react native)的应用。
简单总结:纯编译框架在做到性能优化的同时失去了灵活性,react就是纯粹的运行时框架,vue则是中庸之道在各个框架吸取精华
前端小白 用过的框架也只有react 所以说的很片面 肯定也有错的地方,欢迎指正
发生问题的场景
主流的前端框架从实现原理讲,一般分为:
React
)Vue
)Svelte
)你能从以下角度回答该问题么?
需要解决的问题
最佳答案评选标准
最佳答案
悬赏中,欢迎作答...
答题同学须知
答题规范:请在
一次评论
中完成作答,后续修改也请编辑该评论,而不是追加新的评论评选标准:最佳答案由
围观同学
的 👍 和卡颂共同决定评选时间:一般是问题发布24小时后评选,如果问题发布当天回答数较少,问题悬赏金额可能增加,同时悬赏时间也会增加
围观同学须知
对于你满意的答案,请不要吝惜你的 👍,这是评选最佳答案的依据
非答题的评论
会被删除,问题相关讨论请在赏金猎人群中进行