这篇文章记录了我在使用Vue和React时对它们的一些区别的一些思考,不仅仅局限于它们,还有经常一起使用的比如Vuex/Redux的工具。因为涉及的内容比较多,也许下面的每一个点都可以写成一篇文章。这次先做一个简单的总结,有空再做一个详细的topic。监控数据变化的实现原理不同。Vue通过getter/setter和一些函数劫持,可以准确的知道数据的变化,不需要特别优化也能达到很好的性能。React默认比较引用。如果不优化(PureComponent/shouldComponentUpdate)可能会导致大量不必要的VDOM重新渲染。为什么React不能准确监控数据变化?这是因为Vue和React的设计理念不同。Vue使用可变数据,而React强调数据。不可变的。所以应该说没有好坏之分,在构建大型应用时,Vue更简单,React更健壮。因为一般都会用到Vuex、Redux这样的数据层框架,所以这部分就不做过多解释了,在***中的vuex和redux的区别中也会提到。数据流向的区别大家都知道Vue默认支持双向绑定。在Vue1.0中,我们可以实现两种双向绑定:父子组件之间,props可以通过v-model双向绑定实现组件与DOM之间的双向绑定。也就是说,父子组件不能双向绑定(但是提供了一个语法糖来帮助你通过事件自动修改它们),Vue2.x已经不鼓励组件对其props进行任何修改。所以现在我们只有组件之间的双向绑定<–>DOM。然而,React从一开始就不支持双向绑定。React一直提倡一种单向的数据流,他称之为onChange/setState()模式。但是,由于我们一般使用Vuex、Redux等状态管理框架进行单向数据流,所以往往感受不到这种差异。HoC和mixins我们在Vue中组合不同功能的方式是通过mixins,而在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等,这里就不说了。在React中,也有对应的三种方法:父组件可以通过props向子组件传递数据或回调可以通过context进行跨层通信,其实和provide/inject类似。可见React本身是不支持自定义事件的。Vue中子组件向父组件传递消息有两种方式:事件和回调函数,而Vue更喜欢使用事件。但是在React中,我们都使用回调函数,这可能是它们之间最大的区别。模板渲染方式的区别是表面上的,模板的语法不同。React通过JSX渲染模板,而Vue通过扩展的HTML语法渲染模板。从深层次来说,模板的原理不同,这是它们本质的区别:React在组件JS代码中通过原生JS实现模板中的常用语法,比如插值、条件、循环等,都是通过JS语法实现的Vue通过与组件JS代码分离的单独模板中的指令实现。例如,条件语句需要v-if来实现这一点。我个人更喜欢React的做法,因为它更纯粹和原生,而Vue的做法有些独特,而且会把HTML搞乱。举个例子来说明React的好处:react中的render函数支持闭包特性,所以我们导入的组件可以直接在render中调用。但是在Vue中,因为模板中使用的数据必须挂在this上进行一个中转,所以我们导入一个组件后,需要在components中重新声明一次,这显然很奇怪但又不得不这样。Vuex和Redux的区别从表面上看,store注入和使用有一些区别。在Vuex中,$store是直接注入到组件实例中的,因此可以更灵活的使用:使用dispatch和commit通过mapState提交更新或者直接通过this.$store来读取数据在Redux中,我们每个组件都需要显示使用connect连接所需的props和dispatch。另外,Vuex更加灵活。Components既可以dispatchaction也可以commitupdates,而Redux只能dispatch,不能直接调用reducer修改。在实现原理上,最大的区别有两点:Redux使用的是不可变数据,而Vuex的数据是可变的。Redux每次都是用新状态替换旧状态,而Vuex在检测数据变化时直接修改Redux通过diff比较差异,而Vuex其实和Vue一样,通过getter/setter进行比较(如果看Vuex源码代码,你就会知道,其实他是直接在内部创建了一个Vue实例来跟踪数据的变化)而这两点的区别其实是因为React和Vue的设计理念的不同。React更倾向于构建稳定的大型应用,非常专业。相比之下,Vue更倾向于简单快速地解决问题,更加灵活,不严格遵守规章制度。因此,也会给人一种大项目用React,小项目用Vue的感觉。
