Vue和react差别:
1 作用域问题
Vue中可以在this(即全局作用域)上绑定很多属性、方法(通常都是utils类的方法),methods、data、computed这些属性也全都绑到了this上,Vue也有全局组件的概念而React没有,全局注册了组件在各级子组件中无需import可以直接用,换句话说,全局环境比较混乱,当然从另一个角度历届混乱的话那就是灵活性强
而React没有全局组件的概念,用到什么组件必须手动import,工具方法也是同样的,没有一个全局的地方存放,而必须手动import,有些时候比较繁琐,所以React的项目写下来会发现import了很多重复的东西,我怎么对这些重复的import进行再进一步封装避免冗余是一个问题,当然,看起来是更加清晰一些,而且也有助于按需加载,而对于Vue来说,看到this.xxx后根本不知道xxx到底是props,还是data,还是computed,还是mixin里的,还是自己往this上随便挂了个啥东西
在这一点上,vue3的设计在向react靠拢
2 错误处理方面
react在子组件报错时如果没有用ErrorBoundary,直接就白屏了
但Vue不会
3 页面交互处理方面
react想要在props、state发生变化时做一些事情,需要在钩子中做对应的操作,比如props发生改变就可以在componentWillReceiveProps,state、props的改变都会进入componentDidUpdate里面,hooks出现了之后,都是通过useEffect来做依赖变化对应的处理的
而对于Vue,则比较依赖于$watch
4 关于语法糖方面 jsx vs Vue单文件组件
在react中,如果把一个对象写在模板中,例如如下写法:
<div>{obj}</div>
控制台会直接报错,通常排查这种报错有时会比较困难,因为我的页面中jsx引用的变量特别多,我怎么知道是哪个对象类型的变量导致的这个错误呢?
但Vue不会,Vue最起码会展示出obj.toString()之后的结果,便于我判断哪里出问题了,可以针对性的去改
剩下的就是诸如用的顺手、文档比较好、生态比较好,这都是一些很难有定论、无关痛痒的东西,目前没有发现哪个业务场景是只有react能做而Vue不能做,相反的情况也并没有出现
5 更新data/state数据之后,是否可以立即使用
在react里面,无论是类组件里调用this.setState,还是函数组件中调用setXxx这样的useState hook返回的方法,如果再这些代码后面试图以同步的方式获取设置的值,是获取不到的,如果想要得到的话,在setState的第2个参数里可以传入回调拿到该值
在Vue里面,给data赋值之后,是可以通过同步的方式在后面的代码中拿到设置的值的,因为Vue中给data设置值的同时其实也触发了属性的set钩子,set钩子会遍历与该属性所有的Dependency对应的Watcher去执行
例如:
this.region = 'beijing'
// 此处假设formatRegion是一个计算属性
console.log(this.region, this.formatRegion)
看似同步的两行代码,在this.region被赋值为北京时,会触发组件的渲染Watcher执行(如果页面上用到了这个region属性),也会触发计算属性formatRegion对应Watcher的执行,所以第2行代码在console时都能拿到最新的值
6 对应组件库的设计思路上
对于弹框组件,通常的业务场景为一个按钮,点击它可以控制弹框的显隐
Vue对应的element-ui实现方式为el-dialog,点击按钮触发显隐的逻辑在父组件中,需要通过传入一个visible属性来控制
而react对应的antd的话,习惯把按钮和弹框封到一个组件里,在内部处理其显示隐藏的逻辑,外面调用时这些显隐相关的属性无需传入
7 设计思想
两种框架的优化思路不同,Vue响应式更新是以组件为最小更新单元的,在注册了一大堆watch之后,能快速定位到更新的地方进行更新,范围最大也就是重新对发生更新的dom所处的组件进行虚拟DOM重新生成,再进行diff,最后更新DOM
但react是无论在什么地方setState或者调用了hook返回的set钩子,都是从根节点开始遍历effectList进行更新
但react的任务虽然很大,但是引入fiber架构后,就可以利用浏览器的空闲时间将任务打散,不会阻塞主进程,并没有占用DOM渲染的时间,因此页面看起来并没有多卡顿
8 源码组成
对于Vue,源码主要由响应式、编译、组件化三部分组成,react则是任务调度、通过fiber架构进行任务的收集和执行、DOM渲染三个层级
二者的diff算法既有类似的地方又有各自特殊的逻辑
对于react来说,组件的概念较为弱,仅仅是作为fiber的一种类型的节点而存在,专门针对组件这种类型的节点做的渲染层面的特殊逻辑并不多
9 API及功能
react每个版本对外暴露的api非常稳定,降低了版本升级的学习成本,而Vue的话1.x-3.x之间api差异比较大,需要频繁的翻阅api文档熟悉新的语法,学习成本高一些
10 diff算法的区别
- 共同的地方:
大体的节点移动逻辑一致:
都是先进行特殊案例的快捷对比,然后对于尾部增加或删除了节点的情况则通过判断oldChildren或newChildren的指针在其中一个移动到尾部的时候另一个还没有移动到尾部来判断出来到底是新增还是删除,并做对应操作,最后进入乱序对比
乱序对比时,都是先把oldChildren做一个映射,然后再将newChildren进行遍历,去映射里寻找是否存在可复用的节点
无论是react还是Vue,节点复用时都是把节点往后挪,所以可复用的节点特点就是 在遍历newChildren的过程中,对应于oldChildren中的索引,在newChildren中的位置依然是升序排列的最新节点
- 不同的地方: 整体上来看,Vue处理了比React更多的优化情况
Vue进入patch方法后,按照“新旧、开头结尾”这两种情况两两组合定义了4个指针 因此,其快捷对比模式有头头对比、尾尾对比、头尾对比、尾头对比,只要命中这4种情况,便可跳出循环完成diff操作
但React里面,只有newIndex oldIndex两个指针
React里面多设置了一个lastPlacedIndex用来标识最后一个(最新一个?)可以复用(不需要移动?)的节点在oldFiber中的位置索引,但在Vue中,似乎oldStartIndex和lastPlacedIndex作用差不太多
11 样式处理方面
vue的单文件组件SFC中对于style标签提供了scoped属性用于样式隔离,大概原理是在编译的时候新增一层namespace
但React并没有提供这方面的能力,样式隔离需要我们自己管理namespace,或者引入第三方库区解决
12 版本升级/学习成本方面
vue从1.x升级到2.x,从2.x升级到3.x,甚至2.x小版本升级,语法 写法都有很多不同
但react的api从最初版到现在的最新版差异很小,升级时需要再次学习的成本很低