一文讲解关于Vue和React区别

这篇文章主要讲述了了Vue和React它们的不同之处的一些思考,不仅局限于它们本身,也会包括比如Vuex/Redux等经常搭配使用的工具。因为涉及到的内容很多,请认真对待接下来的内容哦!

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

Vue通过getter/setter以及一些函数的劫持,能精确知道数据变化,不需要特别的优化就能达到很好的性能。

React默认是通过比较引用的方式进行的,如果不优化(PureComponent/shouldComponentUpdate)可能导致大量不必要的VDOM的重新渲染。

为什么React不精确监听数据变化呢?这是因为Vue和React设计理念上的区别,Vue使用的是可变数据,而React更强调数据的不可变。所以应该说没有好坏之分,Vue更加简单,而React构建大型应用的时候更加鲁棒。

因为一般都会用一个数据层的框架比如Vuex和Redux,所以这部分不作过多解释,在最后的vuex和redux的区别中也会讲到。

数据流的不同

大家都知道Vue中默认是支持双向绑定的。在Vue1.0中我们可以实现两种双向绑定:

1、父子组件之间,props可以双向绑定。

2、组件与DOM之间可以通过v-model双向绑定。

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

所以现在我们只有组件<-->DOM之间的双向绑定这一种。

然而React从诞生之初就不支持双向绑定,React一直提倡的是单向数据流,他称之为onChange/setState()模式。

不过由于我们一般都会用Vuex以及Redux等单向数据流的状态管理框架,因此很多时候我们感受不到这一点的区别了。

HoC和mixins

在Vue中我们组合不同功能的方式是通过mixin,而在React中我们通过HoC(高阶组件)。

React最早也是使用mixins的,不过后来他们觉得这种方式对组件侵入太强会导致很多问题,就弃用了mixinx转而使用HoC,关于mixin究竟哪里不好,可以参考React官方的这篇文章MixinsConsideredHarmful

而Vue一直是使用mixin来实现的。

为什么Vue不采用HoC的方式来实现呢?

高阶组件本质就是高阶函数,React的组件是一个纯粹的函数,所以高阶函数对React来说非常简单。

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

组件通信的区别

其实这部分两个比较相似。

在Vue中有三种方式可以实现组件通信:

父组件通过props向子组件传递数据或者回调,虽然可以传递回调,但是我们一般只传数据,而通过事件的机制来处理子组件向父组件的通信

子组件通过事件向父组件发送消息。

通过V2.2.0中新增的provide/inject来实现父组件向子组件注入数据,可以跨越多个层级。

另外有一些比如访问$parent/$children等比较dirty的方式这里就不讲了。

在React中,也有对应的三种方式:

父组件通过props可以向子组件传递数据或者回调。

可以通过context进行跨层级的通信,这其实和provide/inject起到的作用差不多。

可以看到,React本身并不支持自定义事件,Vue中子组件向父组件传递消息有两种方式:事件和回调函数,而且Vue更倾向于使用事件。但是在React中我们都是使用回调函数的,这可能是他们二者最大的区别。

模板渲染方式的不同

在表层上,模板的语法不同。

React是通过JSX渲染模板。

而Vue是通过一种拓展的HTML语法进行渲染。

但其实这只是表面现象,毕竟React并不必须依赖JSX。

在深层上,模板的原理不同,这才是他们的本质区别:

React是在组件JS代码中,通过原生JS实现模板中的常见语法,比如插值,条件,循环等,都是通过JS语法实现的。

Vue是在和组件JS代码分离的单独的模板中,通过指令来实现的,比如条件语句就需要v-if来实现。

对这一点,我个人比较喜欢React的做法,因为他更加纯粹更加原生,而Vue的做法显得有些独特,会把HTML弄得很乱。举个例子,说明React的好处:

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

Vuex和Redux的区别

从表面上来说,store注入和使用方式有一些区别。

在Vuex中,$store被直接注入到了组件实例中,因此可以比较灵活的使用:

使用dispatch和commit提交更新

通过mapState或者直接通过this.$store来读取数据。

在Redux中,我们每一个组件都需要显示的用connect把需要的props和dispatch连接起来。

另外Vuex更加灵活一些,组件中既可以dispatchaction也可以commitupdates,而Redux中只能进行dispatch,并不能直接调用reducer进行修改。

从实现原理上来说,最大的区别是两点:

Redux使用的是不可变数据,而Vuex的数据是可变的。Redux每次都是用新的state替换旧的state,而Vuex是直接修改。

Redux在检测数据变化的时候,是通过diff的方式比较差异的,而Vuex其实和Vue的原理一样,是通过getter/setter来比较的(如果看Vuex源码会知道,其实他内部直接创建一个Vue实例用来跟踪数据变化)。

而这两点的区别,其实也是因为React和Vue的设计理念上的区别。React更偏向于构建稳定大型的应用,非常的科班化。相比之下,Vue更偏向于简单迅速的解决问题,更灵活,不那么严格遵循条条框框。因此也会给人一种大型项目用React,小型项目用Vue的感觉。

(0)

相关推荐