vue 和 react 比较

从概念开始

  • React官网说:React是用于构建用户界面的Javascript库。
  • Vue官网说:Vue是用于构建用户界面的Javascript渐进式框架。

一个说自己是库,一个说自己是框架,我们就先从这个细节说起。如下图

Vue说自己是框架,是因为官方提供了从声明式渲染到构建工具一整套东西。

React说自己是库,是因为官方只提供了React.js这个核心库,路由、状态管理这些都是社区第三方提供了,最终整合成了一套方案。

两者最终达到的效果是相同的,也就是渐进式的解决方案,根据需求复杂度的不同,Vue和React都可以提供相匹配的、合适的解决方案。

何为声明式渲染

何为声明式渲染,为何这种方式能在前端界大行其道呢?

声明式渲染指的是只需操作数据,不是操作视图(一般指DOM),数据就自然映射到视图上。当开发人员设定好数据和视图的映射关系后,操作数据就是声明式的编程。

没有声明式渲染,前端的业务逻辑和视图逻辑就要耦合在一起,难为开发和维护。声明式渲染将视图和业务逻辑拆分开,让开发人员只需要关注数据和业务逻辑,能应对前端负责的业务,也能保证数据准确的反应在视图上。

响应式数据 VS 不可变数据

Vue和React都要解决一个问题,如何让数据变化后,通知到视图更新。

Vue采用了响应式数据,对数据进行劫持,Vue2是对属性进行劫持,Vue有了新的API Proxy,可以对对象进行代理。当数据变化时,通知劫持的观察者更新视图。

React是调用方法通知视图更新,数据不可变的好处是在重新渲染时只需比对数据引用是否变化,就知道是否数据变化了,进而React决定是否要进行重渲染。

响应式数据的好处是可以准确的知道哪个组件受影响了,需要进行重渲染,进行精准更新,但也同时因为劫持数据和收集依赖要耗费额外的性能。不可变数据并没有监听哪些组件会受自己的改变而需要重新渲染,所以要自数据变动组件及所有子组件都需要重新渲染,需要在子组件中添加性能优化相关的代码,保证跟自己相关的数据没有变化时不重新渲染,这需要额外的心智负担,但也没有响应式数据那些额外开销。

JSX VS 模版

声明式渲染的另一端是视图,其实JSX和模版咋一看区别不大,都是XML样子的东西。

JSX可以最大程度利用JS的能力,比如下面这段代码,逻辑判断、循环甚至递归都可以自由使用。

javascript
复制代码function TreeNode(props) {
  const { children } = props;
  if(!children) return <div>暂无节点</div>;
  
  return (
    <div>
      {children 
          ? children.map(child => <TreeNode key={child.id} {...child} />)
          : "暂无节点"}
    </div>
  );
}

相比之下模版语法,要想实现逻辑判断或循环,就需要借助模版语法v-if、v-for等。

同一个问题,比如组件要接收父组件传递过来的视图片段,来看一下React和Vue分别是怎样解决呢。答案是JSX会使用props.children或render prop,模版会使用语法slot。

可以看到JSX是简洁的,一些功能的实现都是利用JS原生的能力,而Vue是提供便捷的语法帮助你解决问题。

还有一点区别是,模版会在编译时编译成render函数,在运行时供Vue使用,这给了Vue优化的空间,在Vue3中,针对模版的编译有了标记元素、静态提升等优化手段,后续在运行时更快的创建虚拟DOM和diff对比。而JSX就是JS,没有了编译过程这个优化空间。

至于Vue有v-model这种双向绑定,只是一种语法糖,不算两个库的关键区别。

组件化

组件化是两个库等编写复杂应用的又一基石特性。这里要提得就是单向数据流,数据都是从父组件流向子组件。数据等流向清晰,便于管理。

组件

Vue的组件更像一个对象,无论我们使用Vue2的Options API 还是Vue3的Composition API,都是填充组件对象的内容,扩展组件的功能。

React分函数组件和类组件。函数组件更符合React整体的调调,也就是函数式。函数式的思维,把React抽象为UI=Fn(State),React将State映射成UI,这是纯的部分,这个过程中发生的其他事情,被称之为副作用。我认为这也是函数式的精髓所在,它总是告诉你自己的主线是什么,保持主线的纯粹,其他方便的东西都是副作用,是主线的支线流程。这样,我们的应用就有了清晰的逻辑。

对比之下,React也更倾向让组件单一职责,分容器组件和展示组件,而这在Vue中没有刻意的强调,Vue就是让组件完成独立的功能即可。

在具体实践中,React组件要更注意性能优化,也就是控制自身要不要重新渲染,而Vue却不需要。这还是响应式数据带来的区别,Vue能准确的知道数据变更后会触发哪些组件进行更新。而React中State变化以后,没有优化的情况下,会导致使用State及其所有子组件进行重渲染。

路由

两个库的路由库的核心功能一样,暂时不多说,后续等我充分研究后这部分内容。

状态管理

什么情况下,要使用状态管理呢?

如下图所示,当数据不总是以一种线性的,单向的方式流动、许多不相关的组件以相同的方式更新状态等情况出现,就应该考虑使用状态管理了。

React使用Redux后示意图

如上图所示,使用状态管理后,数据的变化和流向又变得清晰。状态管理可以很好的配合复杂组件树的情况。

心智模型对比

Vuex仍然是基于响应式数据的,通过Action(异步)和Mutation(同步)的改变State。State绑定到视图的computed上,Action和Mutation绑定到视图的methods上,就打通了视图和状态管理。

Redux仍然是基于不可变数据的,是函数式的思维,通过Action来处理副作用,通过Reducer来更新State。通过store.subscribe回调通知外界State变化。

完整度对比

Vuex除了维护状态,也处理异步,同样提供了连通Vue的mapState等函数,相对来说比较完整。而且Vuex将State、Getters、Mutation、Action统一放在一个对象里,更加集中方便管理。

Redux的内容更加纯粹,只负责维护状态,如果需要处理异步,需要加入中间件,如果需要连通React,需要引入react-redux库。

其他感想

还有个Mbox状态管理库,也是基于响应式数据的,可以应用到React上,我个人目前感觉还是Redux更加适合React,因为React就尊崇函数式的思想,这点上Redux非常契合,可以用一样的心智模型来思考。

还有Pinia,相比于Vuex,Mutation不再存在更加简洁,且Pinia更加适合Vue3。从这我们也可以看出无论Vuex还是Pinia,都是为Vue量身打造的状态管理库。而Redux的设计专注于自身设计,再跟React进行组合。

Fiber架构

上面是从渐进式的脉络来对比了两个库,接下来我们看看React和Vue近年来的主要更新,再思考彼此是否有类似的更新,都做的怎么样。

React为什么要采用Fiber架构

首先要说的就是React 16推出的Fiber架构。说的是解决React渲染性能问题,我想说的是React 15的渲染性能很差吗?

我觉得即使没有Fiber架构,React 15的渲染性能也没有很差,在使用React 15进行实际项目的开发时,也是可以满足绝大部分项目的性能要求的,除非项目巨大,并且开发者对性能优化方面做得不够。

所以有种说法说因为Vue性能好,React性能差才要进行Fiber架构是没有道理的。Vue和React性能差不多,只不过是因为React要保持比较好的性能,在性能优化方面要做得工作,要比Vue多花些心思。

所以,react采用Fiber架构,不是因为性能差,而是因为追求卓越,让应用有更加流畅的表现。

Fiber架构产生的后续影响

Fiber架构的调度逻辑是复杂的,从React16 到React 18在不断优化中,而Fiber架构带来给开发者的问题是,是否要在我们的应用中利用Fiber架构的优势,开启并发模式。

下面看看各版本如何开启并发模式。

javascript
复制代码// 对于React 16和17,如果使用ReactDOM.render,是不开启并发模式的
ReactDOM.render(<App />, rootNode);
// 对于React 16和17,如果使用ReactDOM.createRoot(rootNode).render(<App />),是开启并发模式的
ReactDOM.createRoot(rootNode).render(<App />);

// 对于React 18,改变了策略,统一使用ReactDOM.createRoot(rootNode).render(<App />)来启动应用。
// 但只有当开发者使用跟并发相关的新特性useDeferredValue和useTransition,才会开启并发模式,否则还是同步模式
const App = () => {
  const [count, updateCount] = useState(0);
  const [isPending, startTransition] = useTransition();

  const onClick = () => {
    // 使用了并发特性useTransition
    startTransition(() => {
      // 本次更新是并发更新
      updateCount((count) => count + 1);
    });
  };
  return <h3 onClick={onClick}>{count}</h3>;
};

所以正如我上头所说,无论16到18版本,我们大部分还是用同步更新就够了,除非你觉得有必要使用并发更新的时候才需要使用。

Hooks VS Composition API

React 16.8发布了Hooks,Vue3也紧随其后推出了Composition API。无论Hooks和Composition API,都很大程度的改变了开发者代码的书写方式。

在写组件代码时,两者达到的效果有异曲同工之处,就是让逻辑更紧密的业务代码可以放在一块,在组件之间可以复用状态逻辑。

javascript
复制代码// 在Vue中,可以利用Composition API将逻辑紧密的代码放在一块
import { ref, onMounted, onUnmounted } from 'vue'
// 按照惯例,组合式函数名以“use”开头
export function useMouse() {
  // 被组合式函数封装和管理的状态
  const x = ref(0)
  const y = ref(0)

  // 组合式函数可以随时更改其状态。
  function update(event) {
    x.value = event.pageX
    y.value = event.pageY
  }

  // 一个组合式函数也可以挂靠在所属组件的生命周期上
  // 来启动和卸载副作用
  onMounted(() => window.addEventListener('mousemove', update))
  onUnmounted(() => window.removeEventListener('mousemove', update))
  // 通过返回值暴露所管理的状态
  return { x, y }
}

// 同理,在React中,利用Hooks将逻辑紧密的代码放在一块
import React, { useState, useEffect } from 'react';

function FriendStatus(props) {
  const [isOnline, setIsOnline] = useState(null);  useEffect(() => {    function handleStatusChange(status) {      setIsOnline(status.isOnline);    }    ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);    return () => {      ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);    };  });
  if (isOnline === null) {
    return 'Loading...';
  }
  return isOnline ? 'Online' : 'Offline';
}

但不同的是,Hooks对于React有更重要的意义,就是扩展了函数式组件的能力,让函数式组件拥有状态,让函数式组件可以做到一切。让函数式组件成为了React中一等一的公民。也更加符合React的调调,用函数式的思维来思考。UI不过是经过函数将State进行映射,至于这过程中发生的其他事情,都是副作用。

跨平台方案对比

React和Vue最知名的两个跨端框架,就是React Native和Weex了。

先说说Weex

Weex发展历程

我们先捋一下Weex发展时间线,从出生到死亡。

  • 2015年阿里无限内部使用。
  • 2016年4月阿里巴巴在Qcon大会上宣布开源
  • 2016 年底加入了 Apache 软件基金会
  • 2017年12月从Apache Incubator退休,也就是不符合Apache孵化器的所有要求,没能成为一个成熟的开源项目。主要原因是没有足够的开源贡献者。Weex 将会回归到 alibaba/weex 继续维护。
  • 我查看github上的 alibaba/weex 项目,最近的release版本是2017年5月的0.30版本。可以说没有再继续维护了,凉凉。
  • 2021年面试阿里一个团队,说他们内部在使用Weex 2.0,不是个开源版本,更多信息不得而知。

实际使用Weex体验

特别要说的一点是,Weex不支持模版语法v-show。在我看来这能反应React API简洁的一个优势,API越简洁,基于它构建的框架需要兼容的API越少。

由于Weex看起来已经逐渐退出历史舞台,更多跨端开发体验,放在下面谈React Native时候说。

再说说React Native

RN(React Native简称)从2015年开源至今,一直处于活跃更新状态。所以要考虑跨平台应用开发,RN是值得被考虑的。

我们先看看两个方案的口号对比。

  • RN:Learn Once, Write Anythere。(RN只是降低的是学习成本,针对不同平台可能还需要单独开发)
  • Weex:Write once, Run Everywhere。(写一次,在哪都能跑)

RN口号是严谨的,它考虑到了跨平台的复杂性且难以统一,编写跨平台应用的代码,本身就是要具备一些挑战性的。Weex就显得有些吹牛皮了。

实际使用RN体验

相较于开发Web,RN的组件类似于DOM,但不同于DOM,RN组件会被翻译成原生组件。

同样的,RN的样式也是CSS-Like,也跟CSS相似,但不完全一样。React和RN在编程体验相同的地方是都是React的逻辑。关于组件和样式的情况,Weex也是类似的,毕竟两个方案的解决思路是相同的。

javascript
复制代码import React from 'react';
import { Text, View } from 'react-native';

const YourApp = () => {
  return (
    <View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
      <Text>
        Try editing me! 🎉
      </Text>
    </View>
  );
}

export default YourApp;

RN另一个让人觉得充满挑战的点是频繁更新,原则上它每个月都会更新,它需要跟随原生平台的更新和变化,以确保应用程序的兼容性和性能。所以我们在使用RN方案的时候,也要跟上脚步,关注版本变化,进行框架升级。

Next.js vs Nuxt.js

接下来说说React和Vue的两个重磅框架,Next.js和Nuxt.js。

Next.js

主要特点

  • 服务端渲染:支持SSR和SSG两种方式,有更好的SEO,首屏渲染性能。
  • 基于文件的路由:简单灵活,可以实现页面之间的无缝跳转和传递参数,使用户在浏览网站时体验流畅且一致。
  • 全栈能力:在Next.js框架下,同样可以定义API,可以说Next.js是一个全栈框架。

服务端组件

额外要说的是Next 13推出的服务端组件,让服务端渲染从页面级细化到组件级别,真是太厉害了。另外函数式组件再次在Next.js中发挥威力,在服务端是不支持类组件的。

Nuxt.js

可以说是Next.js的Vue版本,主要特性是类似的,服务端渲染,基于文件的路由,还有全栈能力,不过Nuxt目前还不支持服务端组件。

对比总结

概括的说,React是最求简洁和函数式的,这两点也确实在跨平台方案和大型框架如Next.js中发挥了威力。还有一个重要的影响点就是,给项目中的React升级是容易的,也得益于React对自身暴露API的谨慎。

Vue追求易用和上手,但在跨平台方案和大型框架落了下风。但如果是开发Web应用,Vue同样是值得选择的好技术栈。暂时总结到这里,后续再学习,有新的心得再补充进来。

总结

1.框架本质不同

Vue本质是MVVM框架,由MVC发展而来;

React是前端组件化框架,由后端组件化发展而来。

2.数据流的不同

Vue1.0中可以实现两种双向绑定:父子组件之间,props可以双向绑定;组件与DOM之间可以通过v-model双向绑定。Vue2.x中去掉了第一种,也就是父子组件之间不能双向绑定了(但是提供了一个语法糖自动帮你通过事件的方式修改),并且Vue2.x已经不鼓励组件对自己的 props进行任何修改了。

React一直不支持双向绑定,提倡的是单向数据流,称之为onChange/setState()模式。不过由于我们一般都会用Vuex以及Redux等单向数据流的状态管理框架,因此很多时候我们感受不到这一点的区别了。

3.监听数据变化的实现原理不同

Vue通过 getter/setter以及一些函数的劫持,能精确知道数据变化。

React默认是通过比较引用的方式(diff)进行的,如果不优化可能导致大量不必要的VDOM的重新渲染。为什么React不精确监听数据变化呢?这是因为Vue和React设计理念上的区别,Vue使用的是可变数据,而React更强调数据的不可变,两者没有好坏之分,Vue更加简单,而React构建大型应用的时候更加鲁棒。

4.HoC和mixins

Vue组合不同功能的方式是通过mixin,Vue中组件是一个被包装的函数,并不简单的就是我们定义组件的时候传入的对象或者函数。比如我们定义的模板怎么被编译的?比如声明的props怎么接收到的?这些都是vue创建组件实例的时候隐式干的事。由于vue默默帮我们做了这么多事,所以我们自己如果直接把组件的声明包装一下,返回一个HoC,那么这个被包装的组件就无法正常工作了。

React组合不同功能的方式是通过HoC(高阶组件)。React最早也是使用mixins的,不过后来他们觉得这种方式对组件侵入太强会导致很多问题,就弃用了mixinx转而使用HoC。高阶组件本质就是高阶函数,React的组件是一个纯粹的函数,所以高阶函数对React来说非常简单。

5.组件通信的区别

Vue中有三种方式可以实现组件通信:父组件通过props向子组件传递数据或者回调,虽然可以传递回调,但是我们一般只传数据;子组件通过事件向父组件发送消息;通过V2.2.0中新增的provide/inject来实现父组件向子组件注入数据,可以跨越多个层级。

React中也有对应的三种方式:父组件通过props可以向子组件传递数据或者回调;可以通过 context 进行跨层级的通信,这其实和 provide/inject 起到的作用差不多。React 本身并不支持自定义事件,而Vue中子组件向父组件传递消息有两种方式:事件和回调函数,但Vue更倾向于使用事件。在React中我们都是使用回调函数的,这可能是他们二者最大的区别。

6.模板渲染方式的不同

在表层上,模板的语法不同,React是通过JSX渲染模板。而Vue是通过一种拓展的HTML语法进行渲染,但其实这只是表面现象,毕竟React并不必须依赖JSX。

在深层上,模板的原理不同,这才是他们的本质区别:React是在组件JS代码中,通过原生JS实现模板中的常见语法,比如插值,条件,循环等,都是通过JS语法实现的,更加纯粹更加原生。而Vue是在和组件JS代码分离的单独的模板中,通过指令来实现的,比如条件语句就需要 v-if 来实现对这一点,这样的做法显得有些独特,会把HTML弄得很乱。

举个例子,说明React的好处:react中render函数是支持闭包特性的,所以我们import的组件在render中可以直接调用。但是在Vue中,由于模板中使用的数据都必须挂在 this 上进行一次中转,所以我们import 一个组件完了之后,还需要在 components 中再声明下,这样显然是很奇怪但又不得不这样的做法。

7.渲染过程不同

Vue可以更快地计算出Virtual DOM的差异,这是由于它在渲染过程中,会跟踪每一个组件的依赖关系,不需要重新渲染整个组件树。

React在应用的状态被改变时,全部子组件都会重新渲染。通过shouldComponentUpdate这个生命周期方法可以进行控制,但Vue将此视为默认的优化。

如果应用中交互复杂,需要处理大量的UI变化,那么使用Virtual DOM是一个好主意。如果更新元素并不频繁,那么Virtual DOM并不一定适用,性能很可能还不如直接操控DOM。

8.Vuex和Redux的区别

从表面上来说,store注入和使用方式有一些区别。在Vuex中,s t o r e 被 直 接 注 入 到 了 组 件 实 例 中 , 因 此 可 以 比 较 灵 活 的 使 用 : 使 用 d i s p a t c h 、 c o m m i t 提 交 更 新 , 通 过 m a p S t a t e 或 者 直 接 通 过 t h i s . store被直接注入到了组件实例中,因此可以比较灵活的使用:使用dispatch、commit提交更新,通过mapState或者直接通过this.store被直接注入到了组件实例中,因此可以比较灵活的使用:使用dispatch、commit提交更新,通过mapState或者直接通过this.store来读取数据。在Redux中,我们每一个组件都需要显示的用connect把需要的props和dispatch连接起来。另外,Vuex更加灵活一些,组件中既可以dispatch action,也可以commit updates,而Redux中只能进行dispatch,不能直接调用reducer进行修改。

从实现原理上来说,最大的区别是两点:Redux使用的是不可变数据,而Vuex的数据是可变的,因此,Redux每次都是用新state替换旧state,而Vuex是直接修改。Redux在检测数据变化的时候,是通过diff的方式比较差异的,而Vuex其实和Vue的原理一样,是通过getter/setter来比较的,这两点的区别,也是因为React和Vue的设计理念不同。React更偏向于构建稳定大型的应用,非常的科班化。相比之下,Vue更偏向于简单迅速的解决问题,更灵活,不那么严格遵循条条框框。因此也会给人一种大型项目用React,小型项目用Vue的感觉。

白银级

  1. 可以加一些偏感受方面的,比如:

React 官方只关注底层,上层应用解决方案都交给社区,所以 React 生态体系丰富,社区强,而且每次更新改动小等 等,而 Vue 是由官方主导开发和维护,生态没那么丰富,虽然上手比 React 简单一些,但每次更新堪称破土重来,改的倒是潇洒得很,这就注定我们学习成本大大增加,并不能做到学习一次就可以一直使用这个框架,1.0 改版 2.0 需要重新学习一遍,2.0 改版 3.0 又要学习一遍,甚至 3.0 到 3.2 都要重学一部分,有些程序员到了 35 退休不是不想干,也是学不动了吧。像是需要记的 API,React 就那么几个,剩下的自己去写就行了,Vue 虽然在代码维护上有一定优势,可是它的 API 就多得多了,而且还分版本,比如 Vue2 有过滤器,Vue3 却没了,不仅要多记很多 API 和自定义指令,还需要对自己所学的 API 根据版本进行选择使用,感觉不怎么严谨

  1. 也可以将青铜级上面的某些点展开说一下细节,比如:

组件化:

  • Vue2 组件说白了就是一个挂满一堆东西的 Vue 核心类,通过 new Vue() 拿到实例。就是说 Vue 组件的 script 导出的是一个挂满各种 options 的纯对象而已,所以 options API 的 this 指向 Vue 实例,这对我们开发者来说是不透明的,需要文档才能知道上面一堆 this.$xxx 是干嘛用的,而且 Vue 的插件也都是基于 Vue 原型类基础上的,Vue.install 挂到 Vue 实例上去嘛,以保证和第三方库的 Vue 调的是同一个 Vue 对象
  • 而 React 则比较简单,直接定义 render 函数生成 vnode,里面通过四个组件类包装 vnode 而已,不同类型的 vnode 用相对应的组件类处理,就像责任划分一样,各自只负责自己的。而且 React 类组件都是继承于 React.Component 类,它的 this 指向我们自定义的类,可以说对我们开发者来说是透明的

hook:

  • React hook 是根据调用顺序来确定下一次重新渲染时的 state 是来源于哪个,所以有一些限制,比如不能在循环/条件判断/嵌套函数里使用,而且必须在函数最顶层调用 hook 等
  • Vue3 hook 是基于响应式实现的,它是声明在 setup 里,一次组件实例化只调用一次 setup,而 React 每次重新渲染都要重新调用,性能上自然不言而喻,而且可以在循环/条件判断/嵌套函数里使用,并且正因为是基于响应式实现的,还自动实现了依赖收集,而 React 需要手动传入依赖等

等等...

黄金级

起码得深入源码吧,比如:

响应式:

  • Vue2 响应式的特点就是依赖收集,数据可变,自动派发更新,初始化时通过 Object.defineProperty 递归劫持 data 所有属性添加 getter/setter,触发 getter 的时候进行依赖收集,修改时触发 setter 自动派发更新找到引用组件重新渲染
  • Vue3 响应式使用原生 Proxy 重构了响应式,一是 proxy 不存在 Vue2 响应式存在的缺陷,二是性能更好,不仅支持更多的数据结构,而且不再一开始递归劫持对象属性,而是代理第一层对象本身。运行时才递归,用到才代理,用 effect 副作用来代替 Vue2 里的 watcher,用一个依赖管理中心 trackMap 来统一管理依赖代替 Vue2 中的 Dep,这样也不需要维护特别多的依赖关系,性能上取得很大进步
  • 相比 Vue 的自动化,React 则是基于状态,单向数据流,数据不可变,需要手动 setState 来更新,而且当数据改变时会以组件根为目录,默认全部重新渲染整个组件树,只能额外用 pureComponent/shouldComponentUpdate/useMemo/useCallback 等方法来进行控制,更新粒度更粗一些

Diff 算法:

  • Vue2 是同层比较新老 vnode,新的不存在老的存在就删除,新的存在老的不存在就创建,子节点采用双指针头对尾两端对比的方式,全量diff,然后移动节点时通过 splice 进行数组操作
  • Vue3 是采用 Map 数据结构以及动静结合的方式,在编译阶段提前标记静态节点,Diff 过程中直接跳过有静态标记的节点,并且子节点对比会使用一个 source 数组来记录节点位置及最长递增子序列算法优化了对比流程,快速 Diff,需要处理的边际条件会更少
  • React 是递归同层比较,标识差异点保存到 Diff 队列保存,得到 patch 树,再统一操作批量更新 DOM。Diff 总共就是移动、删除、增加三个操作,如果结构发生改变就直接卸载重新创建,如果没有则将节点在新集合中的位置和老集合中的 lastIndex 进行比较是否需要移动,如果遍历过程中发现新集合没有,但老集合有就删除

钻石级

这得要脱离代码层面,上升到更加宏观的层面吧,区别摆在那里是死的,固定的,就主要看人怎么说了,比如

  1. 以突出核心思想和设计理念开头:

我觉得最主要就是核心思想和设计理念上的区别,React 一开始定位的就是 UI 开发的新思路,这种思想说白了就是要改变开发者,我制定规则,你们都照我的来,因为背靠大公司(facebook),所以不缺用户,而 Vue 是尽可能降低前端开发的门槛来适应不同的开发者,让开发者怎么爽怎么来,正是因为这种设计理念上的差别对后续设计也产生了一些不可逆的影响,或者说这两框架后续架构的变化都是围绕这个来的。

  1. 以突出数据管理方式开头:

我觉得这两最主要的区别是在数据管理方式上,虽然都是数据驱动,但 Vue 是响应式的,React 是手动 setState,可以说正是因为这个对后面架构的设计都产生了一些不可逆的影响,或者说这两框架后续架构的变化都是围绕这个来的。

主要体现在这些方面:

比如 Vue 是对数据进行劫持/代理,它对监测数据的变化更加精准,动了多少数据就触发多少更新,更新粒度很小,而 React 推崇函数式,这是没办法感知数据变化的,就是说不知道什么时候应该刷新,而且即便是手动 setState 触发更新,它也也不知道哪些组件需要刷新,而是渲染整个 DOM,说白了就是无脑刷新嘛,这样就导致性能不好,所以后面只能不断通过其他办法来避免不必要的刷新,或者优化无脑刷新的性能。当然 Vue 也不是那么完美,它实现精准刷新也是有代价的,就是需要给每个组件配置监视器,管理依赖收集和派发更新,这同样是有消耗的。且不是说性能谁好吧,我们可以对比下这两框架版本迭代可以发现,React 迭代是增加了一个个避免刷新的钩子函数或者 API 还有采用 Fiber 的架构来做时间分片也是来优化渲染的性能。而 Vue1/Vue2/Vue3 每个版本虽然改的东西多,但核心都是围绕响应式来优化的,所以我觉得这是这两框架之间最重要的区别

比如正是这种设计上的区别,也直接影响了 hooks 的实现和表现,React hook 底层是基于链表实现的,每次组件被 render 的时候都会按顺序执行所有 hooks,而且正因为底层是链表,每个 hook 的 next 是指向下一个 hook 的,所以我们写代码是不能在不同的 hooks 调用里使用条件判断/函数嵌套之类的,因为这会导致执行顺序不对,从而出错。而 Vue hook 只会被注册调用一次,因为它是声明在 setup 里,一次组件实例化只调用一次 setup,Vue 之所以能避开这些问题,主要还是得益于数据响应式,不需要链表对 hooks 进行记录,而是直接对数据代理观察,但它也有困扰的地方,就是不得不返回一个包装对象,通过 .value 获取。因为在 JS 里基础类型只有值,没有引用,或者说只存在栈里,使用完就回收了,无法追踪后续变化,自然做不到数据的代理和拦截,这算是这个设计的一个缺点吧

再比如编译优化的问题,Vue 能够做到数据劫持,再到 Vue3 动静结合的 Diff 思想也得益于它的模板语法实现了静态编译。就是能做到预编译优化,可以静态分析,在解析模板时能根据解析到的不同的标签、文本等分别执行对应的回调函数来构造 AST,而 React 虽然 JSX 语法更加灵活,可也正是因为这样导致可以优化的地方不足,重新渲染时就是一堆递归调用 React.createElement,无法从模板层面进行静态分析,也就做不到双向绑定,即使是很厉害的 fiber,也是因为伤害已经造成,所以通过时间分片的优化来弥补伤害吧,因为已经无法在编译阶段进行优化了,这也是这个设计所带来的问题吧

项目选型怎么考虑?怎么选择?

从加载速度,运行时性能来说,我觉得这两个框架综合各种场景应该是没什么质的差别的。硬要说的话,Vue 在更新时性能优化方面需要的心智负担可能会少那么一点,特别是 Vue3,而 React 如果不注意,容易导致一些组件无用的 Diff,但其实实际项目中真正能遇到这种性能瓶颈的也是极少数,所以(这里有两种说法):

(如果公司主要用 Vue 技术栈的话):所以总的来说我觉得 Vue 性能上会更有优势一点,特别是 Vue3 更加灵活,有很好的可扩展性,同时有更快的渲染速度和更小的打包体积。从 mixins 到 HOC 到 render props 再到 hooks,React 基本已经废掉了过去很多基于组件的逻辑抽象模式,抹掉了 JSX 对比模板的一个优势,Vue3 中现在也都能做到,所以我会偏向 Vue3。

(如果公司主要用 React 技术栈的话):所以总的来说我觉得要是一些不大的系统或者 H5 就用 Vue,因为不管是上手还是开发难度上都很简单,开发效率也高嘛,而且它有更小的打包体积,毕竟在移动端网络差异大的情况下,资源体积是非常重要的。但像是一些中后台系统,或者一些大点的项目,会越做越大的,多人协作开发的,就用 React,因为它的函数式编程有更加灵活的结构和可扩展性,丰富的生态圈和工具链,解决方案多,后期也更方便迭代与维护,还适用原生 APP,所以我会偏向 React。

你觉得这两框架哪个厉害

这个,我觉得吧,我们讨论这个问题的时候,可能由于咱俩关于这一块儿的信息不对等,只是表达自己想法的话,有可能会变成两个阵营的,而且即使证明了一个比另一个牛比,也不意味着我的项目就牛比了,反正好用就都学,让自己变得厉害才更靠谱一点


 

作者:沐华
链接:https://juejin.cn/post/7238199999733088313
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值