今天是 React 和 Angular2 的一个对比。在 Peter 这里想听到谁都不得罪的那种对比太难了,所以今天也不例外,我会全力来黑 A 挺 R ,事先声明我没有用 A 做过真正的项目,但是我也会努力做到不乱喷,有凭有据,信息量充足。因为英文世界里,其实大牛们的言论已经非常多了,Peter 喜欢做一个知识的搬运工。
有人说拿他们两个直接对比不太合适,因为 R 是一个 library ,而 Angular2 是一个 framework 。 其实我觉得没有什么不合适啦。选择了 React 之后,自然就会选择跟他配套的其他库去组织成自己的一套框架,自然就会形成一套不同于 Angular 的做事方法。再打个比方,Angular 好像一个计算机,React 是一个部件。所以,可以说 React 和 Angular2 之间在 2016 年会是一场白刃战。
就在几年前,前端大牛们其实都有一个共同的烦恼:代码因充满了 jQuery 选择器和回调函数而十分凌乱。Angular1 在2011年的出现很好地解决了这个问题。 Angular 并不是最早的 JS 框架,但是在我的印象中,SPA (单页面应用),JS framework 这些概念被推向风口浪尖,Angular 的能量应该是最大的。 使用 AngularJS 开发的项目拥有极好的可维护性,AngularJS 拥有一系列简单易用的功能,有利于快速开发大型的 Web 项目。
稍微给 Angular 说几句好话。因为 Angular 是个框架( framework ),所以使用了 Angular 就一切具备了,可以避免选配件的麻烦。比如像我们选择了 React 之后,其实还要自己选择各个第三方库,去提供路由( route )控制,API 调用,单向数据流控制,测试,依赖管理等各种功能。不过,React 的灵活也是一种优势。例如,很多人认为学 React 上来就要学 Webpack/Redux 这一套东西,其实这是不对的,这些东西很强大也很复杂,Peter 建议在 React 入门之后再去学。而在前期,直接用 React 去局部改写自己的任何的项目都是可以的,React 真的比任何的框架都容易上手。即使后面要开发更为复杂的功能,也可以用 React+Meteor 来配合完成,依然要比上 Redux 那套思路简单。
所以 React 在 2013 年出现后,Angular1 就有了一个强大的竞争者。React 实践了各种革命性的思路,其中最明显的一点就是,组件化。组件化将会是未来 Web 页面,甚至是其他 UI 开发领域的默认思路,嗯,我是这么认为的,2015年冬天的时候,我就发过微信群
不管你用不用 React ,但是如果你还没有组件化,就 out 了!
这是好几个月以前了,不过最近越来越发现自己说的没错。React 出来之后,整个前端高手界对组件化概念几乎是全盘接受的态度,所有的(对,就是所有)框架都在用组件化思想来改写。就以当时还是地位最显赫的 Angular 来说,在 Angular1 的时代,没有 component(组件)这个概念,而是用 directives, controllers, scope 和 template 这些概念综合使用来达成 component 类似的效果。但是这里 Peter 来插一句,大家数数,前面一共四个概念,这四个概念 React 中都没有的,所以 Angluar 很脑残的一点是发明了大量的概念,用户的角度来说增加了学习成本。用 React 创始人的说法就是:
凡是对一个问题没有想清楚的人,总会发明出各种无用的概念来
好,别人喷你无所谓,Angluar 自己也是不争气,2014 年发布了 Angular2 。 A2 中把 A1 之中所有的这些概念推翻,直接照搬 React 的 component ,对 Angluar 进行了彻底重写,A2 跟 A1 几乎就是两个框架,用 A1 的项目想要升级到 A2 根本就不可能。
Typescript 是微软的作品,它是 JS 的一个扩展,拥有强大的 Type(类型)检查,和面向对象编程的功能。使用 Angular 需要使用 Typescript。多年不用 Windows 了,对微软的生态系统不了解,所以也让我很不愿意碰 Typescript 。而且像类型检查这样的功能明显是学 Java 的,服务大项目,这个跟 Peter 一贯的思路也不太相符:创业公司,小项目,最高的个人生产力。
ES6 是下一版的 JS 标准,当前浏览其中原生支持的是 ES5 。ES6 提供了 ES5 所没有的面向对象的功能,但是没有类型检查。虽然 ES6 的各种新功能浏览器还没有支持,但是通过 Babel 这样的“转译”工具,已经可以把我们写的 ES6 语法的程序,转换成 ES5 ,交给浏览器去执行了。所以 ES6 已经大量用于实际产品开发了,目前就我观察,ES6 要比 Typescript 的受欢迎程度更高。
React 拥抱 ES6 。Babel 这个项目,同时可以转译 ES6 和 React 的 JSX 语法。对比一下 github/babel 和 github/typescript ,Star 数目还是 Babel 有明显优势的。
当然,不管是 React 或者是 Angular2 都可以用原生 JS ,也就是 ES5 来开发,不过目前随着转译工具变得越来越好用,目前感觉使用 ES6 或者 Typescript 是更加高明的选择。
JSX 看起来和 HTML 差不多,React 可以把它编译成纯 JS 去执行。一个 React 组件之中,我们会把 html 标签和 JS 代码写到一起,但是组件文件本质上是一个 JS 文件,所以 html 标签部分就按照 JSX 的语法去写。html 和 JS 写到一起这个做法,以前我们认为是违反最佳实践的,但是其实现在看来原来的“非侵入 JS”的所谓最佳实践是多么傻。JS 要操作的就是 html 中的那些标签名,class/id 名,所以如果都写到一个文件中,那不仅仅是代码容易读,容易修改,而且编辑器的自动补齐功能也更能帮上忙,有百利而无一害。组件化的思路根本上就是分离复杂度的思路变了,React 这里是按照功能模块分,而传统的最佳实践是按照技术类型分离( js/css/html 分离),弱爆了。
而在 Angular2 中依然是使用 html 模板( template )。这样做有一个很大的弱点就是如果代码写错了,编译的时候是不会报错的,而运行的时候通常也就是直接失败,也看不到准确的报错信息。而 JSX 在编译的时候是要先变成 JS 在去浏览器中执行的,所以一旦写错,编译的时候就会有行号明确的报错信息。瞅瞅,这个是不是太棒!
注:上图来自这篇文章 ,演示了当我们的代码缺少结束标签时的报错情况。
JavaScript-Centric 大意是:”以 JS 为中心“。而 Angular2 是 HTML-Centric 的。可以这样说
Angular2 是把 JS 嵌入到 HTML 中,而 React 是把 HTML 嵌入到 JS 中
刚看这句话可能没有感觉,经过了长时间对 React 的使用,我渐渐觉得跟 React 相反的思路就是一个设计大缺陷,这样说起来就很残酷了,因为 JSX 是 React 的发明,除了 React 之外,其他的所有框架都是有这个大缺陷的。
根本的原因就是 HTML 从来都不如 JS 擅长表达逻辑。所以更为高明的做法是:我们去强化 JS ,让 JS 能更好的支持标签,而不是去强化 html 让它去支持逻辑。一个页面组件永远是要 html 和 js 协同工作才能实现的,那么 React 的 JS-centric 的思路要比 Angular ,Ember ,和 Knockout 的 HTML-centric 的思路高明的多。因为 JS-Centric 带来的是简便。
Angular2 继续了 Angular1 的思路,继续想要强化 HTML 。所以在使用 A2 的时候,如果要实现哪怕再平常不过的循环或者条件判断,也必须使用 A2 自创的语法。例如
<ul>
<li *ngFor="#hero of heroes">
</li>
</ul>
而对应的,如果要用 React 实现相同的效果,只需要用 JS 语法就可以了
<ul>
{ heroes.map(hero =>
<li key={hero.id}>{hero.name}</li>
)}
</ul>
所以可以大致总结成这样一句话:
学习 Angular ,就要学一堆它自创的语法,学 React ,就学纯 JS 就可以了
Angular2 是 Angular1 的一个重大改进,拥抱了组件化的思想。但是,A2 的 HTML-Centric 的设计思路对比起 React 的 JS-Centric 的思路来显得愚蠢,所以我认为 React 将会是未来。
最后插一句八卦:Angular 虽然是 Google 的产品,但是有谁知道哪个大型项目是用 Angular 的吗?没人知道,因为就是没有。而 React 是真正用在 Facebook.com 这种千亿级别的项目的,而且像 instagram.com ,airbnb.com ,可汗学院, uber.com,twitter 这些几百亿美元级的项目就更多了。国内的一线互联网公司也都在转 React ,其中急先锋就是阿里。