React vs Angular: порівняльна інформація для розробників

18

Від автора: ця стаття призначена для розробників, які знайомі з Angular 1.x і хотіли б дізнатися більше про React. Ми розглянемо різні підходи до створення насичених веб-додатків, перекриттів функціональних можливостей і недоліків, які React не може заповнити. Після ознайомлення ви дізнаєтеся про проблеми, які React має намір вирішити, і про те, як ви можете використовувати знання, які ви вже почали використовувати React у власних проектах.

Фрэймворки проти Бібліотек

Angular це фреймворк, тоді як React — це бібліотека, орієнтована тільки на шарі подання. Існують плюси і мінуси, пов’язані з використанням як фреймворків, так і колекцій слабо пов’язаних бібліотек.

Фрэймворки намагаються запропонувати повне рішення, і можуть допомогти організувати код через шаблони і угоди, якщо ви є частиною великої команди. Однак коли пишете, наявність великого API додає когнітивну навантаження, буде витрачено набагато більше часу на читання документації і запам’ятовування шаблонів — особливо в перші дні, коли тільки йде навчання.

Слабо пов’язані бібліотеки з маленькими API легше вивчати, проте коли у вас виникнуть проблеми, ви будете вирішувати їх великою кількістю коду, або ж вам доведеться підключати зовнішні бібліотеки. Зазвичай це призводить до написання свого фреймворку для зменшення розмірів шаблона.

З коробки

Angular дає вам багатий набір функцій для створення веб-додатків. Серед його можливостей:

HTML-шаблони з динамічними виразами у подвійних дужках {{ }}

вбудовані директиви, наприклад, для розширення можливостей HTML ng-modelng-repeatng-class

контролери для групування логіки і передачі даних до подання

двостороння прив’язка як простий спосіб синхронізувати подання і контролер

великий набір модулів, наприклад $http для зв’язку з сервером і ngRoute для маршрутизації

настроювані директиви для створення власного синтаксису HTML

ін’єкції залежностей для обмеження впливу об’єктів на певні частини програми

послуги для загальної бізнес-логіки

фільтри для допомоги при форматуванні.

З іншого боку, React дасть:

Синтаксис JSX для шаблонів з виразами JavaScript в одиночних дужках {}

компоненти, які найбільше схожі на директиви елемента Angular.

React не опирається, коли справа доходить до іншої частини структури програми, і заохочує використання стандартних JavaScript API поверх абстракцій фреймворка. Замість того, щоб надавати оболонку, таку як зв’язок $http-сервера, ви можете використовувати fetch(). Ви можете використовувати різні конструкції, такі як служби і фільтри, але React не буде надавати абстракцію для них. Ви можете помістити їх в модулі JavaScript і зажадати їх у своїх компонентах по мірі необхідності.

Тобто, в той час як Angular дає вам більше абстракцій для звичайних завдань, React навмисно уникає цього, щоб ви частіше писали стандартний JavaScript і використовували зовнішні залежності для всього іншого.

Попереднє завантаження

Ініціалізація додатків Angular вимагають наявності модуля, списку залежностей і кореневого елемента.

let app = angular.module(‘app’, [])
let root = document.querySelector(‘#root’);
angular.element(root).ready(function() {
angular.bootstrap(корінь, [‘app’]);
});

Точкою входу для React є рендеринг компонента в кореневий вузол. Також можливі кілька кореневих компонентів:

let root = document.querySelector(‘#root’);
ReactDOM.render(, root)

Шаблони

Будова подання Angular складне і має безліч завдань. HTML-шаблони містять поєднання директив і виразів, які пов’язують уявлення і пов’язані з ним контролери між собою. Дані в різних контекстах проходять через $scope.

У React всі компоненти йдуть вниз, дані поступають в одному напрямку від вершини дерева до компонентів вузлових листя. JSX є найбільш поширеним синтаксис написання компонентів, перетворюючи знакову структуру XML в JavaScript. Хоча це більше схоже на синтаксис шаблону, він компілюється в вкладені виклики функцій.

const App = React.createClass({
render: function() {
return (

{ 2 + 1 }

)
}
})

Скомпільований код, наведений нижче, повинен пояснити, як JSX вираження вище посилаються на виклик функцій: createElement(component, props,children)

var App = React.createClass({
render: function render() {
return React.createElement(
Component,
null,
React.createElement(«div», null, 2 + 1),
React.createElement(Component, { prop: «value» }),
React.createElement(
Component,
{ time: new Date().getTime() },
React.createElement(Component, null)
)
);
}
});

Директиви шаблонів

Давайте розглянемо, як деякі з найбільш використовуваних шаблонів в Angular будуть написані в компонентах React. Тепер у React немає шаблонів, так що ці приклади — це код JSX, який буде знаходитися всередині компонента render функції. Наприклад:

class MyComponent extends React.Component {
render() {
return (
// JSX lives here
)
}
}

ng-repeat

  • { word }

Ми можемо використовувати стандартні механізми циклізації JavaScript, наприклад, map для отримання масиву елементів в JSX.

    { words.map((word)=>

  • { word }
  • )}

ng-class

У React ми створюємо список класів, розділених пропусками для властивості className, на власних пристроях. Для цієї мети звичайно використовується існуюча функція, така як className Джеда Уотсона.

Можна думати про ці атрибути в JSX так, ніби ви встановлюєте властивості безпосередньо на вузлах. Ось чому це className, а не ім’я атрибута класу.

formNode.className = «active error»;

ng-if

Yep

if … else оператори, не працюють усередині JSX, тому що JSX — це просто синтаксичний цукор для звязку функцій і побудови об’єктів. Для цього прийнято використовувати тернарные оператори або переміщати умовну логіку в початок методу візуалізації поза JSX.

// ternary

{ enabled ?

Enabled

: null }

// if/else outside of JSX
let node = null;
if (enabled) {
node =

Enabled

;
}

{ node }

ng-show / ng-hide

Living

Ghost

У React ви можете безпосередньо встановити властивості стилю або додати свій CSS клас утиліт, щоб приховати елементи типу .hidden {display: none } (як це робить Angular).

Living

Ghost

Living

Ghost

Тепер замість спеціального синтаксису шаблону і атрибутів потрібно буде використовувати JavaScript для досягнення бажаного результату.

Приклад компонента

Компоненти React більше схожі на директиви Angular . Вони використовуються, насамперед, для абстрагування складних структур DOM і поведінки всередині багаторазових фрагментів. Нижче наведено приклад компонента слайд-шоу, який приймає масив слайдів, відображає список зображень з навігаційними елементами і відстежує його власне activeIndex стан, щоб виділити активний слайд.

app.controller(«SlideShowController», function($scope) {
$scope.slides = [{
imageUrl: «allan-beaver.jpg»,
caption: «Allan Allan Al Al Allan»
}, {
imageUrl: «steve-beaver.jpg»,
caption: «Steve Steve Steve»
}];
});
app.directive(«slideShow», function() {
return {
restrict: ‘E’,
scope: {
slides: ‘=’
},
template: `

  • React vs Angular: порівняльна інформація для розробників
    {{ slide.caption }}
  • {{ $index + 1 }}

`,
link: function($scope, element, attrs) {
$scope.activeIndex = 0;
$scope.jumpToSlide = function(index) {
$scope.activeIndex = index;
};
}
};
});

Компонент слайд-шоу в Angular

Цей компонент в React буде відображатися в межах іншого компоненту і передавати дані слайдів через реквізити.

let _slides = [{
imageUrl: «allan-beaver.jpg»,
caption: «Allan Allan Al Al Allan»
}, {
imageUrl: «steve-beaver.jpg»,
caption: «Steve Steve Steve»
}];
class App extends React.Component {
render() {
return
}
}

У компонентів React є локальна область дії, яку, викликавши, можна змінити. Будь-які зміни стану змушують компонент повторно відображати себе .this.statethis.setState({ key: value })

class SlideShow extends React.Component {
constructor() {
super()
this.state = { activeIndex: 0 };
}
jumpToSlide(index) {
this.setState({ activeIndex: index });
}
render() {
return (

    {
    this.props.slides.map((slide, index) => (

  • React vs Angular: порівняльна інформація для розробників
    { slide.caption ? { slide.caption } : null }
  • ))
    }

    {
    this.props.slides.map((slide, index) => (

  • this.jumpToSlide(index) }>{ index + 1 }
  • ))
    }

);
}
}

Події в React виглядають як обробники подій in-line старої школи, такі як onClick. Не турбуйтеся: всередині все робиться як треба, створюються високопродуктивні делеговані обробники подій.

Компонент слайд-шоу в React

Двостороння прив’язка

Angular довірена директива ng-model і змінна $scope формують зв’язок, де дані можуть ходити в обидві сторони від елемента форми до властивостей JS-об’єкта в контролері.

app.controller(«TwoWayController», function($scope) {
$scope.person = {
name: ‘Bruce’
};
});

Hello {{ person.name }}!

React уникає цього шаблону на користь одностороннього потоку даних. Тим не менш, ті ж типи уявлень можуть бути побудовані з обома шаблонами.

class OneWayComponent extends React.Component {
constructor() {
super()
this.state = { name: ‘Bruce’ }
}
change(event) {
this.setState({ name: event.target.value });
}
render() {
return (

this.change(event) } />

Hello { this.state.name }!

);
}
}

Тут input це «керований вхід». Це означає, що її значення змінюється тільки коли викликається функція «render» (по кожному штрихові в прикладі вище). Сам компонент називається «stateful», тому що він управляє своїми власними даними. Це не рекомендується для більшості компонентів. Ідеальним є збереження компонентів «stateless» і передача даних props через них.

Як правило, «stateful» Container Component або Controller View знаходиться у верхній частині дерева з безліччю дочірніх компонентів «satetless». Для отримання додаткової інформації про це прочитайте, які компоненти повинні мати стан?

Виклик батьків

У той час як дані стікають в одному напрямку, однак ви можете викликати методи на батьківських елементах через callback-функції. Зазвичай це робиться у відповідь на деякі користувальницькі вводи. Ця гнучкість дає вам великий контроль за рефакторинге компонентів в їх найпростіших презентаційних формах. Якщо реорганізовані компоненти взагалі не мають стану, вони можуть бути записані як чисті функції.

// A presentational component written as a pure function
const OneWayComponent = (props)=> (

props.onChange(event.target.value) } />

Hello { props.name }!

);
class ParentComponent extends React.Component {
constructor() {
super()
this.state = { name: ‘Bruce’ };
}
change(value) {
this.setState({name: value});
}
render() {
return (

Hello { this.state.name }!

)
}
}

На перший погляд це може здатися рухом по колу, якщо ви знайомі з двостороннім прив’язкою даних. Перевага наявності безлічі невеликих презентаційних «німих» компонентів, які просто беруть дані props і їх рендеринг, полягає в тому, що вони за замовчуванням простіше, а прості компоненти мають набагато менше помилок. Це також не дозволяє інтерфейсу перебувати у невизначеному стані, що часто відбувається, якщо дані знаходяться в декількох місцях і повинні підтримуватися окремо.

Ін’єкція залежностей, сервіси, фільтри

Модулі JavaScript — один з кращих способів обробки залежностей. Їх можна використовувати з допомогою такого інструменту, як Webpack , SystemJS або Browserify.

// An Angular directive with dependencies
app.directive(‘myComponent’, [‘Notifier’, ‘$filter’, function(Notifier, $filter) {
const formatName = $filter(‘formatName’);
// use Notifier / formatName
}]
// ES6 Modules used by a component React
import Notifier from «services/notifier»;
import { formatName } from «filters»;
class MyComponent extends React.Component {
// use Notifier / formatName
}

Чи можу я використовувати і те і інше відразу!?

Так! В існуючому Anglar додатку можна відображати компоненти React. Бен Надэл зібрав хороший пост з скринкастами про те, як візуалізувати компоненти React всередині директиви Angular. Існує також ngReact , який надає директиву react-component для роботи в якості склеювання між React і Angular.

Якщо ви зіткнулися з проблемами продуктивності рендеринга в деяких частинах Angular, можливо, можна підвищити продуктивність, делегуючи частину цього рендеринга для React. При цьому не варто включати дві великі бібліотеки JavaScript, які вирішують багато однакових проблем. Незважаючи на те, що React це тільки шар подання, він приблизно такого ж розміру, як і Angular, так що, ґрунтуючись на такому використанні, вага може бути надмірно великим.

У той час як React і Angular вирішують одні і ті ж проблеми, вони обходяться по-різному. React сприяє функціональному декларативним підходу, коли компоненти є чистими функціями, вільними від побічних ефектів. Цей функціональний стиль програмування призводить до меншої кількості помилок і більш простого міркування.

Що щодо Angular 2?

Компоненти в Angular 2 багато в чому нагадують компоненти React. Приклади компонентів у документації мають клас і шаблон в безпосередній близькості. Події виглядають однаково. У ньому пояснюється, як створювати вистави з використанням ієрархії компонентів точно так само, як якщо б ви будували її React, також у нього включені модулі ES6 для ін’єкцій залежностей.

// Angular 2
@Component({
selector: ‘hello-component’,
template: `

Give me some keys!

{{ values }}

`
})
class HelloComponent {
values=»;
onKeyUp(event) {
this.values += event.target.value + ‘ | ‘;
}
}
// React
class HelloComponent extends React.Component {
constructor(props) {
super()
this.state = { values: «};
}
onKeyUp(event) {
const values = `${this.state.values + event.target.value} | `;
this.setState({ values: values });
}
render() {
return (

Give me some keys!

{ this.state.values }

);
}
}

Велика частина роботи над Angular 2 полягала в тому, щоб DOM-оновлення виконувалися ефективніше. Попередній синтаксис шаблону і складності навколо областей призвели до великих проблем продуктивності у великих програмах.

Повне додаток

У цій статті я зосередився на шаблонах, директивах і формах, але якщо ви створюєте повне додаток, будуть потрібні інші функції, які допоможуть керувати моделлю даних, зв’язком на сервері і маршрутизацією. Коли я вперше навчився працювати з Angular і React, перш ніж почати використовувати їх в реальних додатках, я створив приклад Gmail, щоб зрозуміти, як вони працюють, і подивитися, що таке досвід розробника.

Можливо, вам буде цікаво поглянути на ці приклади додатків, щоб порівняти відмінності React і Angular. Приклад React написаний на CoffeeScript з CJSX, хоча спільнота React зібралося навколо ES6 з Babel Webpack , так що це інструмент, який я б запропонував прийняти, якщо ви тільки починаєте.

https://github.com/markbrown4/gmail-react

https://github.com/markbrown4/gmail-angular

Також є програми TodoMVC, які ви можете порівняти:

http://todomvc.com/examples/react/

http://todomvc.com/examples/angularjs/