Всем известно, что когда мы генерируем коллекцию во view через Angular, то каждый элемент этой коллекции становится observable. Я конечно понимаю и знаю что есть определенный набор библиотек и решений как это обойти, но сегодня речь не об этом. Что же дает нам React? Ну одно из его преимуществ, это jsx синтаксис, который есть не что иным как html в javascript. Также есть возможность создавать reusable компоненты, наследовать их и использовать всю мощь что позволяет делать эта библиотека. Что же приступим.
Первым делом создадим простой проект с банальным названием ng-with-react. Для установки библиотек я воспользуюсь bower. С помощью него установим AngularJS, ReactJS и Twitter bootstrap дабы наше приложение имело хоть какой-то презентабельный вид. Создадим main.js и index.html которые будут иметь код:
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title>AngularJS with Facebook react</title> <link rel="stylesheet" href="app/vendor/bootstrap/dist/css/bootstrap.css"/> <style> .user-list .user-item { border-left: none; border-right: none; } .user-list .user-item:last-child { border-bottom: none; } </style> <script src="app/vendor/angular/angular.js"></script> <script src="app/vendor/react/react.js"></script> <script src="app/main.js"></script> </head> <body ng-app="app"> <div class="container" ng-controller="MainCtrl as main"> <div class="page-header"> <h1>A experiment with AngularJS and ReactJS</h1> </div> <div class="panel panel-default"> <div class="panel-heading">Just AngularJS</div> <ul class="list-group"> <li class="list-group-item" ng-repeat="user in users" ng-click="main.getUser(user)"> {{ user.firstName }} - {{ user.lastName }} </li> </ul> </div> </div> </body> </html>
И
(function(ng, React) var app = ng.module('app', []); var UserFactory = function() { var users = [ {id: 1, firstName: "Denis", lastName: "Stoyanov", age:26}, {id: 2, firstName: "Alex", lastName: "Alexeev", age:24}, {id: 3, firstName: "Peter", lastName: "Petrov", age:21}, {id: 4, firstName: "Ivan", lastName: "Ivanov", age:20} ]; return { users: users }; }; var UserCtrl = function($scope, $log, User) { $scope.users = User.users; this.getUser = function(user) { $log.info('A selected user %O', user); }; }; app.factory('User', [UserFactory]); app.controller('MainCtrl', ['$scope', '$log', 'User', UserCtrl]); return app; })(angular, React);
Соответственно.
Что у нас есть в арсенале сейчас. Мы имеем простейшее приложение на ng в котором есть простейший контроллер и сервис, который отдает фейковые данные. На стороне представления мы имеем простейший список, который рендерит наши данные. Также у нас есть обработчик по клику на элемент, который записывает юзера в консоль. Все довольно просто и легко.
Теперь давайте создадим новую директиву для отображения этих же данных, но только через ReactJS. Как подобает в лучших домах Парижа, нам стоит использовать директивы для манипулирования DOM. Для начала создадим React class для рендеринга списка. Его код будет выглядет примерно так:
var UserList = React.createClass({ displayName: "UserList", render: function() { var users = this.props.scope.users; var scope = this.props.scope; var userList = users.map(function(user, index, array) { var clickHandler = scope.$apply.bind(scope, scope.userSelected.bind(null, {user: user})); return React.DOM.li({ className: "user-item list-group-item", onClick: clickHandler }, [user.firstName, user.lastName].join(' - ')); }); return React.DOM.ul( {className:"user-list list-group"}, userList); } });
Как можно заметить в свойствах React есть ряд переменных, которых нам надо будет передать путем простой передачи scope в React class. Также создадим директиву, которая будет использовать этот класс как представление.
var UserDirective = function() { return { restrict: 'AE', scope: { users: '=', userSelected: '&' }, link: function(scope, element, attrs) { scope.$watchCollection('users', function() { React.renderComponent(UserList({scope: scope}), element[0]); }); } }; }; app.directive('userList', UserDirective);
В ней видно, что будем мы ее использовать как элемент или же аттрибут, в нее будут переданы данные с юзерами и функция для вывода юзера в консоль. Чтобы наше представление отображалось при изменении коллекции и создадим простейший watcher и на его изменения будет перерисовывать наше представление. И наконец мы срендерим наш React class в тот елемент, на который был повешен аттрибут user-list. В index.html после рендеринга на Angular добавим такой код:
<div class="panel panel-default"> <div class="panel-heading">AngularJS with ReactJS</div> <div user-list users="users" user-selected="main.getUser(user)"></div> </div>
Вот такими простыми манипуляциями мы связали Angular и React. Приложение простейшее, но оно дает понять концепт и в дальнейшем можно усложнять. По моим тестам при 2000 елементов view на React было в 5 раз быстрее чем на Angular.
На скриншоте мы можем видеть, что у view на React нет байндингов в отличии от ReactJS.
Также мы можем посмотреть, что нам сгенерировал React.
Надеюсь мой эксперимент будет кому-то полезен. Я считаю, что надо компоновать решения по их возможностям и если писать на ReactJS представления удобней и в отображении они быстрее, то я буду делать так.
Если есть каки-то нюансы, welcome в комментарии =)
ссылка на оригинал статьи http://habrahabr.ru/post/215607/
Добавить комментарий