当前位置: 首页 > 科技观察

前端:Vue和React的优势是什么?两者的核心区别是什么?

时间:2023-03-14 14:43:23 科技观察

Vuetemplatevs.JSX我觉得这只是“解决同一个问题的不同实现思路”,完全可以根据开发者的个人喜好来决定。退一步讲,在Vue中使用JSX并非不可能;同样的,JSX也不是不能实现Vue模板的特性,比如模板指令,我们完全可以从工程的角度去实现:当然,这需要我们基于抽象语法树AST,的思想实现一个解析模板指令的插件也很简单:Vue和React实现复用的方面我觉得没必要重复,因为在实现复用的道路上,Vue和React都经历过:Mixin->Hoc(Vue比较少用,模板设置模板,有点奇怪)->renderprop(Vue有类似的想法实现为槽)->hooks(Vue3.0functionbasedAPI)在这方面,UI层面的复用本身是没有问题的:因为组件化本身就是天生可组合的。重要的是逻辑复用:hooks和Vue3.0函数式API的设计无疑是最先进的,一定程度上解耦了逻辑复用和组件表达,避免了“面向生命周期编程”的麻烦。顺便实现更好的可组合性和TS友好性。我真正想深入的是这几个方面:Vue和React的核心差异,以及核心差异对后续设计的“不可逆”影响。Vue和React在API设计风格和理念上的差异(甚至是作者的个人魅力)。在工程预编译和构建阶段,AOT和JIT优化的本质区别和设计要点首先,我想说清楚:用Evanyou的话来说:双向绑定是针对表单的,双向绑定表单的绑定,说到底只是一个单向绑定值+onChange事件监听的语法糖。这并不是React和Vue之间概念差异的真实反映。同时,单向数据流不是Vue和React的区别,而是Vue和React的一种默认选择。单向数据流的核心是避免组件自身(未来可重用)状态的设计,强调状态提升,集中管理。但我真正认为的是React和Vue的概念差异,对后续设计和实现产生不可逆影响的是:Vue进行数据拦截/代理,更灵敏准确地检测数据的变化,间接影响一些后续实施。(如钩子、基于函数的API)提供了极大的便利。我们稍后会提到这一点;React推崇函数式风格,直接进行局部刷新(或者重新渲染),比较粗糙,但是更简单,把我们的开发带回了古代,刷新就好,前端开发很简单。但React不知道什么时候“应该刷新”,触发部分重新更改是由开发人员手动调用setState完成的。ReactsetState导致部分刷新。为了获得更好的性能,React将shouldComponentUpdate生命周期钩子暴露给开发者,以避免不必要的重新渲染(相比之下,Vue使用依赖跟踪,默认是优化状态:你移动多少数据,就可以更新多少被触发,不多也不少,React对数据变化没有感知,它提供React.createElement调用生成虚拟dom)。另外,为了弥补不必要的更新,React会合并setState的行为。因此,setState有时会异步更新,但并不总是“异步”:在设计上,这给开发者带来了额外的“心理负担”,也导致了一些潜在的问题。重申一下,Vue的响应式概念在数据拦截和代理方面没有类似的问题(当然也有批量操作)。这种设计上的差异直接影响了钩子的实现和性能。Reacthook底层是基于链表(Array)实现的。每次渲染一个组件时,所有的钩子都会被顺序执行。因为底层是一个链表,每个钩子的next指向下一个钩子,所以要求开发者不要在不同的钩子调用中使用判断条件,因为if会导致顺序不正确,导致在错误中。下面的代码会报错:相反,vuehook只会被注册和调用一次。Vue之所以能够避免这些麻烦的问题,根本原因在于它对数据的响应是基于响应类型的,并且对数据进行了代理。不需要链表记录hooks,直接观察数据。但是Vue的响应式解决方案也有其自身的问题。例如useState()(实际上被evan命名为value())返回一个值包装器(wrapperobject)。一个被包裹的对象只有一个属性:.value,指向里面被包裹的值。我们知道,在JavaScript中,string、number等原始值类型只有值,没有引用。无论是使用Object.defineProperty还是Proxy,我们都无法跟踪对原始变量的后续更改。所以Vue必须要返回一个wrapper对象,否则无法为基本类型代理拦截数据。这是设计理念带来的一个非常非常小的副作用。从Evanyou的截图我圈出来:简单说一下我的个人看法:其实Mobx在React社区很流行,Mobx采用了响应式的思想,其实Vue也采用了几乎相同的响应式系统。从某种程度上说,React+Mobx也可以算是一个比较笨重的Vue。所以开发人员习惯于组合使用它们,所以(也许)选择Vue会更有意义。再想想,Mobx的火爆或许也从侧面说明了什么样的设计可能是更现代的设计。第二点是在设计理念上。我觉得Evan你很好地体现了中国人谦虚谦虚的优良品质。我选择了比较有代表性的事件系统:1.React事件系统庞大复杂。其中,它暴露给开发者的事件不是原生事件,而是React对合成事件进行了包装,还有很重要的一点就是合成事件是池化的。也就是说,不同的事件可能共享一个合成事件对象。另一个细节是React委托所有事件并将所有事件绑定到文档。请仔细阅读以下代码:你能告诉我它们的输出值是好的吗?2、React中事件处理函数中的this默认不指向组件实例。3.Vue事件系统。Vue话不多说,看图:当然,Vue事件处理函数中的this默认为组件实例。连源码都写的这么“通俗易懂”我简单说说个人看法。从事件API中,我们可以看出前端框架设计的不同思路:React设计是为了改变开发者,提供强大复杂的机制,开发者跟我来;Vue是为开发者适配的,所以开发者可以为所欲为。第三点是预编译优化问题。Vue3.0提出的动静结合的DOMdiff思想,个人认为是Vue近年来“创新”的一个很好的体现。之所以能够做到动静DOMdiff,或者说让这个问题变大:之所以能够做到预编译优化,是因为Vuecore可以对模板进行静态分析。在解析模板的时候,整个解析过程就是使用正则表达式对模板进行顺序解析。当开始标签、结束标签、文本解析完成后,会分别执行相应的回调函数,从而达到构建AST树的目的。我关心的是:React能不能像Vue一样进行预编译和优化??Vue需要做双向数据绑定,数据拦截或者代理,所以需要在预编译阶段对模板进行静态分析,分析视图依赖什么数据进行响应式处理。而React是部分重渲染。React获取或管理的是一堆递归的React.createElement执行调用,无法从模板层面静态分析。所以ReactJSX的过度灵活性导致运行时可用于优化的信息不足。但是,在React框架之外,作为开发者,我们仍然可以通过工程手段实现类似的目标,因为我们可以访问将JSX编译成React.createElement的整个过程。开发者在项目中开发babel插件,将JSX编译成React.createElement,那么优化的方法就是从编写babel插件开始:当然,React也不是没有意识到这个问题,他们也在积极配合prepack。尽量弥补构建优化的先天不足。Prepack也是FaceBook团队的作品。它让你编写纯JavaScript代码,它在构造阶段试图理解代码将做什么,然后生成等效代码,减少运行时的计算量,相当于JavaScript的部分求值器。我用Prepack结合React尝试了一些新东西:比较:这不就是React梦寐以求的吗?React的另一个方向是纤维时间切片。游雨溪说:“React就是伤害已经造成了,无法预测,编译阶段做的多,时间分片等优化只是在弥补伤害。”其实作为React的粉丝,我在这里吹Vue这么久,所以想表达一下自己的想法:这其实是React的一个多管齐下的做法。***,上一个小例子使用Babel插件AST实现了类似的预编译优化:去掉内联函数。预编译后: