这个页面无疑是最难编写的,但我们认为它也是非常重要的。或许你曾遇到了一些问题并且已经用其他的框架解决了。你来这里的目的是看看Vue是否有更好的解决方案。这也是我们在此想要回答的。
客观来说,作为核心团队成员,显然我们会更偏爱Vue,认为对于某些问题来讲用Vue解决会更好。如果没有这点信念,我们也就不会整天为此忙活了。但是在此,我们想尽可能地公平和准确地来描述一切。其他的框架也有显著的优点,例如React庞大的生态系统,或者像是Knockout对浏览器的支持覆盖到了IE6。我们会尝试着把这些内容全部列出来。
React和Vue有许多相似之处,它们都有:
下列部分章节会略微有些过时,因为最近React16+的发布,我们计划在不久的将来和React社区一起重写这部分内容。
在React应用中,当某个组件的状态发生变化时,它会以该组件为根,重新渲染整个组件子树。
如要避免不必要的子组件的重渲染,你需要在所有可能的地方使用PureComponent,或是手动实现shouldComponentUpdate方法。同时你可能会需要使用不可变的数据结构来使得你的组件更容易被优化。
然而,使用PureComponent和shouldComponentUpdate时,需要保证该组件的整个子树的渲染输出都是由该组件的props所决定的。如果不符合这个情况,那么此类优化就会导致难以察觉的渲染结果不一致。这使得React中的组件优化伴随着相当的心智负担。
在Vue应用中,组件的依赖是在渲染过程中自动追踪的,所以系统能精确知晓哪个组件确实需要被重渲染。你可以理解为每一个组件都已经自动获得了shouldComponentUpdate,并且没有上述的子树问题限制。
Vue的这个特点使得开发者不再需要考虑此类优化,从而能够更好地专注于应用本身。
在React中,一切都是JavaScript。不仅仅是HTML可以用JSX来表达,现在的潮流也越来越多地将CSS也纳入到JavaScript中来处理。这类方案有其优点,但也存在一些不是每个开发者都能接受的取舍。
Vue的整体思想是拥抱经典的Web技术,并在其上进行扩展。我们下面会详细分析一下。
在React中,所有的组件的渲染功能都依靠JSX。JSX是使用XML语法编写JavaScript的一种语法糖。
使用JSX的渲染函数有下面这些优势:
有些开发者认为模板意味着需要学习额外的DSL(Domain-SpecificLanguage领域特定语言)才能进行开发——我们认为这种区别是比较肤浅的。首先,JSX并不是没有学习成本的——它是基于JS之上的一套额外语法。同时,正如同熟悉JS的人学习JSX会很容易一样,熟悉HTML的人学习Vue的模板语法也是很容易的。最后,DSL的存在使得我们可以让开发者用更少的代码做更多的事,比如v-on的各种修饰符,在JSX中实现对应的功能会需要多得多的代码。
更抽象一点来看,我们可以把组件区分为两类:一类是偏视图表现的(presentational),一类则是偏逻辑的(logical)。我们推荐在前者中使用模板,在后者中使用JSX或渲染函数。这两类组件的比例会根据应用类型的不同有所变化,但整体来说我们发现表现类的组件远远多于逻辑类组件。
两者另一个重要差异是,Vue的路由库和状态管理库都是由官方维护支持且与核心库同步更新的。React则是选择把这些问题交给社区维护,因此创建了一个更分散的生态系统。但相对的,React的生态系统相比Vue更加繁荣。
React学习曲线陡峭,在你开始学React前,你需要知道JSX和ES2015,因为许多示例用的是这些语法。你需要学习构建系统,虽然你在技术上可以用Babel来实时编译代码,但是这并不推荐用于生产环境。
就像Vue向上扩展好比React一样,Vue向下扩展后就类似于jQuery。你只要把如下标签放到页面就可以运行:
在现在,Weex还在积极发展,成熟度也不能和ReactNative相抗衡。但是,Weex的发展是由世界上最大的电子商务企业的需求在驱动,Vue团队也会和Weex团队积极合作确保为开发者带来良好的开发体验。
Mobx在React社区很流行,实际上在Vue也采用了几乎相同的反应系统。在有限程度上,React+Mobx也可以被认为是更繁琐的Vue,所以如果你习惯组合使用它们,那么选择Vue会更合理。
类React的库们往往尽可能地与React共享API和生态。因此上述比较对它们来说也同样适用。它们和React的不同往往在于更小的生态。因为这些库无法100%兼容React生态中的全部,部分工具和辅助库也可能无法使用。或者即使看上去能工作,但也有可能随时发生不兼容,除非你用的这个类React库官方与React保持严格一致。
在API与设计两方面上Vue.js都比AngularJS简单得多,因此你可以快速地掌握它的全部特性并投入开发。
Vue.js是一个更加灵活开放的解决方案。它允许你以希望的方式组织应用程序,而不是在任何时候都必须遵循AngularJS制定的规则,这让Vue能适用于各种项目。我们知道把决定权交给你是非常必要的。
AngularJS使用双向绑定,Vue在不同组件间强制使用单向数据流。这使应用中的数据流更加清晰易懂。
在Vue中指令和组件分得更清晰。指令只封装DOM操作,而组件代表一个自给自足的独立单元——有自己的视图和数据逻辑。在AngularJS中,每件事都由指令来做,而组件只是一种特殊的指令。
Vue有更好的性能,并且非常非常容易优化,因为它不使用脏检查。
在AngularJS中,当watcher越来越多时会变得越来越慢,因为作用域内的每一次变化,所有watcher都要重新计算。并且,如果一些watcher触发另一个更新,脏检查循环(digestcycle)可能要运行多次。AngularJS用户常常要使用深奥的技术,以解决脏检查循环的问题。有时没有简单的办法来优化有大量watcher的作用域。
Vue则根本没有这个问题,因为它使用基于依赖追踪的观察系统并且异步队列更新,所有的数据变化都是独立触发,除非它们之间有明确的依赖关系。
有意思的是,Angular和Vue用相似的设计解决了一些AngularJS中存在的问题。
我们将新的Angular独立开来讨论,因为它是一个和AngularJS完全不同的框架。例如:它具有优秀的组件系统,并且许多实现已经完全重写,API也完全改变了。
Angular事实上必须用TypeScript来开发,因为它的文档和学习资源几乎全部是面向TS的。TS有很多好处——静态类型检查在大规模的应用中非常有用,同时对于Java和C#背景的开发者也是非常提升开发效率的。
然而,并不是所有人都想用TS——在中小型规模的项目中,引入TS可能并不会带来太多明显的优势。在这些情况下,用Vue会是更好的选择,因为在不用TS的情况下使用Angular会很有挑战性。
Vue相比于Angular更加灵活,Vue官方提供了构建工具来协助你构建项目,但它并不限制你去如何组织你的应用代码。有人可能喜欢有严格的代码组织规范,但也有开发者喜欢更灵活自由的方式。
Angular的学习曲线是非常陡峭的——作为一个框架,它的API面积比起Vue要大得多,你也因此需要理解更多的概念才能开始有效率地工作。当然,Angular本身的复杂度是因为它的设计目标就是只针对大型的复杂应用;但不可否认的是,这也使得它对于经验不甚丰富的开发者相当的不友好。
Ember是一个全能框架。它提供了大量的约定,一旦你熟悉了它们,开发会变得很高效。不过,这也意味着学习曲线较高,而且并不灵活。这意味着在框架和库(加上一系列松散耦合的工具)之间做权衡选择。后者会更自由,但是也要求你做更多架构上的决定。
在Polymer版本中,为了弥补性能,团队非常有限的使用数据绑定系统。例如,在Polymer中唯一支持的表达式只有布尔值否定和单一的方法调用,它的computed方法的实现也并不是很灵活。
Riot3.0提供了一个类似于基于组件的开发模型(在Riot中称之为Tag),它提供了小巧精美的API。Riot和Vue在设计理念上可能有许多相似处。尽管相比Riot,Vue要显得重一点,Vue还是有很多显著优势的: