When we launched React | A JavaScript library for building user interfaces two weeks ago there were a few comparisons to AngularJS (Facebook’s New React JavaScript Library Tutorial Rewritten in AngularJS). We already talked about how React works and its philosophy (React | Why did we build React?), but let's get a little more concrete and look at React and Angular code side-by-side.

To set the record straight: React components are far more powerful than Angular templates; they should be compared with Angular's directives instead. So I took the first Google hit for "AngularJS directive tutorial" (AngularJS Directives Tutorial - Fundoo Solutions), rewrote it in React and compared them.

All of the code in this post is on GitHub at https://github.com/petehunt/angu....

The app

The tutorial creates an "n star" rating widget. Here's what the widget looks like:

You can play with it here: http://jsfiddle.net/abhiroop/G3U...

The HTML page

First let's look at Angular's HTML:

  1. <!DOCTYPE html>
  2. <html ng-app="FundooDirectiveTutorial">
  3. <head>
  4. <title>Rating Directive Demo</title>
  5. <link rel="stylesheet" href="rating.css"/>
  6. </head>
  7. <body ng-controller="FundooCtrl">
  8. Rating is {{rating}} <br/>
  9. Clickable Rating <br/>
  10. <div fundoo-rating rating-value="rating" max="10" on-rating-selected="saveRatingToServer(rating)"></div>
  11. <br/>
  12. Readonly rating <br/>
  13. <div fundoo-rating rating-value="rating" max="10" readonly="true"></div>
  14. <script type="text/javascript" src="Page on Googleapis"></script>
  15. <script type="text/javascript" src="rating.js"></script>
  16. </body>
  17. </html>

It's a pretty straightforward document, except it includes magical HTML attributes. With React you simply mount a component into a plain HTML page via JavaScript. Here's what it looks like:

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <title>Rating Directive Demo</title>
  5. <link rel="stylesheet" href="rating.css"/>
  6. <script type="text/javascript" src="http://dragon.ak.fbcdn.net/hphotos-ak-ash3/851560_459383004151757_22266_n.js"></script>
  7. <script type="text/javascript" src="http://dragon.ak.fbcdn.net/hphotos-ak-prn1/851582_580035725361422_42012_n.js"></script>
  8. <script type="text/jsx" src="rating.js"></script>
  9. </head>
  10. <body>
  11. </body>
  12. </html>

Nothing interesting here (except we're using an in-browser transformer for development; see React | Getting Started for more info). Some JavaScript will mount our component in document.body.

The CSS is shared between the Angular and React versions so I've omitted it.

The JavaScript

Let's look at Angular's JavaScript. It defines a module, a controller and a directive:

  1. angular.module('FundooDirectiveTutorial', [])
  2. .controller('FundooCtrl', function($scope, $window) {
  3. $scope.rating = 5;
  4. $scope.saveRatingToServer = function(rating) {
  5. $window.alert('Rating selected - ' + rating);
  6. };
  7. })
  8. .directive('fundooRating', function () {
  9. return {
  10. restrict: 'A',
  11. template: '<ul class="rating">' +
  12. '<li ng-repeat="star in stars" ng-class="star" ng-click="toggle($index)">' +
  13. '\u2605' +
  14. '</li>' +
  15. '</ul>',
  16. scope: {
  17. ratingValue: '=',
  18. max: '=',
  19. readonly: '@',
  20. onRatingSelected: '&'
  21. },
  22. link: function (scope, elem, attrs) {
  23. var updateStars = function() {
  24. scope.stars = [];
  25. for (var i = 0; i < scope.max; i++) {
  26. scope.stars.push({filled: i < scope.ratingValue});
  27. }
  28. };
  29. scope.toggle = function(index) {
  30. if (scope.readonly && scope.readonly === 'true') {
  31. return;
  32. }
  33. scope.ratingValue = index + 1;
  34. scope.onRatingSelected({rating: index + 1});
  35. };
  36. scope.$watch('ratingValue', function(oldVal, newVal) {
  37. if (newVal) {
  38. updateStars();
  39. }
  40. });
  41. }
  42. }
  43. });

Notice the HTML template defined in a string. The provided linking function tells Angular how to imperatively update the DOM when the rating changes via an explicit callback. There is also a scope which is similar to, but behaves differently than, a JavaScript environment.

Let's look at the React version.

  1. /** @jsx React.DOM */
  2. var FundooRating = React.createClass({
  3. render: function() {
  4. var items = [];
  5. for (var i = 1; i <= this.props.max; i++) {
  6. var clickHandler = this.props.onRatingSelected && this.props.onRatingSelected.bind(null, i);
  7. items.push(<li class={i <= this.props.value && 'filled'} onClick={clickHandler}>{'\u2605'}</li>);
  8. }
  9. return <ul class="rating">{items}</ul>;
  10. }
  11. });
  12. var FundooDirectiveTutorial = React.createClass({
  13. getInitialState: function() {
  14. return {rating: 5};
  15. },
  16. handleRatingSelected: React.autoBind(function(rating) {
  17. this.setState({rating: rating});
  18. alert('Rating selected - ' + rating);
  19. }),
  20. render: function() {
  21. return (
  22. <div>
  23. Rating is {this.state.rating}<br/>
  24. Clickable Rating <br/>
  25. <FundooRating value={this.state.rating} max="10" onRatingSelected={this.handleRatingSelected} />
  26. <br />
  27. Readonly rating <br/>
  28. <FundooRating value={this.state.rating} max="10" />
  29. </div>
  30. );
  31. }
  32. });
  33. React.renderComponent(<FundooDirectiveTutorial />, document.body);

The markup syntax you see is JSX and we've discussed it at length in React | JSX Syntax. We prefer it, but it's not required to use React.

React doesn't have templates since we use JavaScript to generate the markup (via JSX or function calls).

There's no linking function because React figures out how to most efficiently update the DOM for you when your data changes. Just write your render() function and React will keep the UI up-to-date for you.

There are no scopes or other nonstandard concepts besides components (which are just objects) since you're just using plain, familiar JavaScript to express your display logic.

We have plenty of documentation starting with React | Tutorial to explain how all of this works. The important takeaway is that you provide a render() method that declaratively specifies how you want your UI to look. When the data changes, React calls your render() method again, diffs the old return value with the new one and figures out how to update the DOM for you.

React vs AngularJS by the (highly unscientific) numbers

Number of concepts to learn

  • React: 2 (everything is a component, some components have state). As your app grows, there's nothing more to learn; just build more modular components.
  • AngularJS: 6 (modules, controllers, directives, scopes, templates, linking functions). As your app grows, you'll need to learn more concepts.

Lines of code

  • React: 47 (12 HTML, 35 JS)
  • AngularJS: 64 (18 HTML, 46 JS)

Comparing technology is hard.

It's hard to compare two technologies in an objective way in a single blog post. I'm sure it's possible to code golf the Angular example to be smaller than React, so certainly don't take these numbers too seriously.

Using React and AngularJS together

We've designed React from the beginning to work well with other libraries. Angular is no exception. Let's take the original Angular example and use React to implement the fundoo-rating directive.

First, let's bring back the original AngularJS HTML page and add the React dependencies:

  1. <!DOCTYPE html>
  2. <html ng-app="FundooDirectiveTutorial">
  3. <head>
  4. <title>Rating Directive Demo</title>
  5. <link rel="stylesheet" href="rating.css"/>
  6. </head>
  7. <body ng-controller="FundooCtrl">
  8. Rating is {{rating}} <br/>
  9. Clickable Rating <br/>
  10. <div fundoo-rating rating-value="rating" max="10" on-rating-selected="saveRatingToServer(rating)"></div>
  11. <br/>
  12. Readonly rating <br/>
  13. <div fundoo-rating rating-value="rating" max="10" readonly="true"></div>
  14. <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.6/angular.min.js"></script>
  15. <script type="text/javascript" src="http://dragon.ak.fbcdn.net/hphotos-ak-ash3/851560_459383004151757_22266_n.js"></script>
  16. <script type="text/javascript" src="rating-react.build.js"></script>
  17. <script type="text/javascript" src="rating-angular.js"></script>
  18. </body>
  19. </html>

Note: for this example we're precompiling a rating-react.js file using JSX syntax to rating-react.build.js using react-tools.

Next let's strip down the React version to the bare minimum we need to support the directive:

  1. /** @jsx React.DOM */
  2. window.FundooRating = React.createClass({
  3. render: function() {
  4. var items = [];
  5. for (var i = 0; i < this.props.scope.max; i++) {
  6. var clickHandler = this.props.scope.$apply.bind(this.props.scope, this.props.scope.toggle.bind(null, i));
  7. items.push(<li class={i < this.props.scope.ratingValue && 'filled'} onClick={clickHandler}>{'\u2605'}</li>);
  8. }
  9. return <ul class="rating">{items}</ul>;
  10. }
  11. });

And finally, here's what remains of the Angular JavaScript code:

  1. angular.module('FundooDirectiveTutorial', [])
  2. .controller('FundooCtrl', function($scope, $window) {
  3. $scope.rating = 5;
  4. $scope.saveRatingToServer = function(rating) {
  5. $window.alert('Rating selected - ' + rating);
  6. };
  7. })
  8. .directive('fundooRating', function () {
  9. return {
  10. restrict: 'A',
  11. scope: {
  12. ratingValue: '=',
  13. max: '=',
  14. readonly: '@',
  15. onRatingSelected: '&'
  16. },
  17. link: function (scope, elem, attrs) {
  18. scope.toggle = function(index) {
  19. if (scope.readonly && scope.readonly === 'true') {
  20. return;
  21. }
  22. scope.ratingValue = index + 1;
  23. scope.onRatingSelected({rating: index + 1});
  24. };
  25. scope.$watch('ratingValue', function(oldVal, newVal) {
  26. React.renderComponent(window.FundooRating({scope: scope}), elem[0]);
  27. });
  28. }
  29. }
  30. });

We've changed the watch expression to simply call React.renderComponent() whenever the data changes. React is smart enough to do this efficiently. You don't have to write any code to update your UI.

This version clocks in at 62 loc, which is between the pure-React and pure-Angular version.

The conclusion

AngularJS is a great tool for building web apps.

If you like Angular, we think you'll love React because reactive updates are so easy and composable components are a simple and powerful abstraction for large and small applications.

Head on over to React | A JavaScript library for building user interfaces

write by Pete Hunt

Facebook's React vs AngularJS: A Closer Look的更多相关文章

  1. Facebook的React Native之所以能打败谷歌的原因有7个(ReactNative vs Flutter)

    https://baijiahao.baidu.com/s?id=1611028483072699113&wfr=spider&for=pc 如果你喜欢用(或希望能够用)模板搭建应用, ...

  2. 关于 Facebook 的 React 专利许可证

    本文转载自:酷 壳 – CoolShell 作者:陈皓 随着 Apache.百度.Wordpress 都在和 Facebook 的 React.js 以及其专利许可证划清界限,似乎大家又在讨论 Fac ...

  3. 移动应用跨平台框架江湖将现终结者?速来参拜来自Facebook的React Native

    React Native使用初探 February 06 2015 Facebook让所有React Conf的参与人员都可以初尝React Native的源码---一个编写原生移动应用的方法.该方法 ...

  4. Facebook发布React 16 专利条款改为MIT开源协议

    9 月 26 日,用于构建 UI 的 JavaScript 库 React 16 的最新版本上线. Facebook 最终在现有的两种 React 版本中选择了出现 bug 概率最少的一款.这次版本更 ...

  5. ASP.NET Web API 2 external logins with Facebook and Google in AngularJS app

    转载:http://bitoftech.net/2014/08/11/asp-net-web-api-2-external-logins-social-logins-facebook-google-a ...

  6. Facebook的Web开发三板斧:React.js、Relay和GraphQL

    2015-02-26 孙镜涛  InfoQ Eric Florenzano最近在自己的博客上发表了一篇题为<Facebook教我们如何构建网站>的文章,他认为软件开发有些时候需要比较大的跨 ...

  7. 【转】Facebook React 和 Web Components(Polymer)对比优势和劣势

    原文转自:http://segmentfault.com/blog/nightire/1190000000753400 译者前言 这是一篇来自 StackOverflow 的问答,提问的人认为 Rea ...

  8. [React] React Fundamentals: Integrating Components with D3 and AngularJS

    Since React is only interested in the V (view) of MVC, it plays well with other toolkits and framewo ...

  9. Facebook React 和 Web Components(Polymer)对比优势和劣势

    目录结构 译者前言 Native vs. Compiled 原生语言对决预编译语言 Internal vs. External DSLs 内部与外部 DSLs 的对决 Types of DSLs - ...

随机推荐

  1. HTML常用特殊字符

    网页特殊符号HTML代码大全   HTML特殊字符编码大全:往网页中输入特殊字符,需在html代码中加入以&开头的字母组合或以&#开头的数字.下面就是以字母或数字表示的特殊符号大全. ...

  2. PYTHON-面向对象 类 绑定方法

    面向对象三大特性(*****) 1继承 1. 什么是继承 继承是一种新建类的方式,新建的类称之为子类/派生类,被继承的类称之为父类/基类/超类 继承与现实生活中的继承一个意思 (例如 小明继承小明他爹 ...

  3. Pandas详解一

    pandas简介 pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的.Pandas 纳入了大量库和一些标准的数据模型,提供了高效地操作大型数据集所需的工具.pandas提 ...

  4. OCM_第十四天课程:Section6 —》数据库性能调优_各类索引 /调优工具使用/SQL 优化建议

    注:本文为原著(其内容来自 腾科教育培训课堂).阅读本文注意事项如下: 1:所有文章的转载请标注本文出处. 2:本文非本人不得用于商业用途.违者将承当相应法律责任. 3:该系列文章目录列表: 一:&l ...

  5. java多线程快速入门(十)

    synchonizd解决安全性问题 package com.cppdy; class MyThread6 implements Runnable{ private Integer ticketCoun ...

  6. java 标签编译后没有显示

    1.原因现在还不知,试了几个地方可以和不可以 /** * @author feilong */ public class OverLoading { /**@param args put here c ...

  7. 《转》CXF WebService 开发文档-目录索引

    CXF WebService 开发文档-目录索引 上次介绍了Axis的WebService,现在我们来看看CXF是怎么完成WebService的. Axis1 WebService 在线博文: htt ...

  8. django中,如何把所有models模型文件放在同一个app目录下?

    django的每个app目录下,都有自己的models.py文件. 原则上,每个app涉及的数据库,都会定义在这个文件里. 但是,有的数据库,涉及到多个app应用,不是很方便放在一个单独的app里. ...

  9. 最短路径问题 HDU3790 (dijkstra)

    基础的dijkstra问题  加上了花费 #include<bits/stdc++.h> using namespace std; ][][]; ];]; #define INF 9999 ...

  10. 6-10 下落的树叶 uva699

    类似第九题  都是属于比较巧妙的题目  ! 用一个p数组来保存水平值   然后开始built 自然就会按照自左而右的顺序来读取!!!!!!这很重要 #include<bits/stdc++.h& ...