Цель этой статьи - выделить ключевые различия между Angular 2 и React. Angular 2, позаимствовавший многие идеи из React, казался неудобным гибридом Angular 1 и React. Те, кто пришел из React, будут разочарованы соглашениями Angular 2, а те, кто пришел из Angular 1, сочтут структуру компонентов незнакомой. Короче говоря, Angular 2 является значительным улучшением по сравнению с Angular 1, но не соответствует простоте других, более проверенных в боях компонентных фреймворков.
Прежде чем я углублюсь в детали, вот некоторый контекст моего опыта работы с Angular 2.
Несколько месяцев назад у меня была возможность изучить VueJs через приложение для электронных заметок. Этот опыт, хотя временами и разочаровывающий, углубил мое понимание React. Вместо того, чтобы изучать одну структуру, я начал понимать принципы разработки внешнего интерфейса, а не просто запоминать синтаксис и шаблоны.
Мой опыт работы с Angular 2 ничем не отличался. Сначала создавая базовое приложение todo в Angular 1, а затем перестраивая это же приложение в Angular 2, вы понимаете, что ключевые болевые точки пытались решить версия 2. Я не исследовал возможности маршрутизатора или хранилища данных, поэтому эти аспекты исключены из этой публикации. Angular 2 также явно рекомендует использовать TypeScript. Отличия от JavaScript незначительны, но я постараюсь указать на эти отличия по ходу дела.
Ключевые различия между Angular 2 и React
Для правильной реализации компонента в Angular 2 требуется файл component.html (с шаблоном html), файл component.ts (с бизнес-логикой) и файл module.ts (с зависимостями, импортом и объявлениями). Этот сегментированный шаблонный подход будет знаком пользователям Angular 1. Однако пользователям React он временами кажется излишне жестким и многословным.
В вашем файле module.ts для каждого компонента вы должны определить все подкомпоненты внутри этого компонента. Это отличается от React тем, что внедрение этих компонентов отделено от html, в котором вы их визуализируете, что может немного сбивать с толку.
//In React you import the dependency in a component. import Header from './containers/Header'; //Then render that component in your render method. render() { let { user } = this.state; return ( <div className="App"> <Header user={user} signOut={signOut} signIn={signIn}/> </div> ); } //In Angular 2, you import dependencies in the module.ts file and inject them into a component with the declarations property. @NgModule({ declarations: [ AppComponent, HeaderComponent ], ...}) //Then render them in the component.html file. <div> <h1>{{title}}</h1> <HeaderComponent [user]="user"></HeaderComponent> <todoForm [addItem]="addItem"></todoForm> </div>
В Angular 2 вы должны явно указать, что экспортируется из компонента, а также в каждый компонент. Синтаксис для этого может сбивать с толку, поскольку половина ресурсов в Интернете - это бета-версия с другой версией, поэтому вот пример 2 вариантов вывода значений.
//Inside your component.ts file you must explicitly define what each component is expecting to output. Option 1 is using the @Component to define outputs in the array format. @Component({ selector: 'app-root', //what we want to refer to this component as templateUrl: './app.component.html', //html styleUrls: ['./app.component.css'], //scoped css outputs: ['list', 'addItem'] })
Я считаю этот синтаксис идеальным для передачи данных, а не для передачи функций. Для передачи функций я предпочитаю определять их с каждой функцией в классе объекта AppComponent, который затем импортируется как зависимость в файл module.ts.
@Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'], outputs: ['list'] }) export class AppComponent { //properties of the component are similar to state in React title = 'todo list'; //TypeScript sugar can define the type of each attribute and whether it is public or private, so this is a public data field with the type of any array. public list: any[] = []; Output() addItem = (item: string) => { this.list.push(new Item(Date.now(), item, 1)); localStorage.setItem('list', JSON.stringify(this.list)); } }
Значение этого для Angular 2 состоит в том, что разработчики должны явно контролировать, какие данные оставляют компонент. Для платформы, представляющей собой корпоративное программное обеспечение для многих компаний, использующих стек MEAN, это добавляет уровень безопасности и надежности в ваш код. Для тех, кто пришел из других фреймворков, это совершенно чуждое понятие. Я привык передавать свойства через метод рендеринга в React и видел похожие шаблоны в html. Я потратил около часа, пытаясь понять, почему я не могу ничего передать, только чтобы обнаружить этот дополнительный уровень защиты.
Angular 2 требует особого синтаксиса, передающего эти свойства внутри HTML для каждого компонента.
//properties are passed with brackets <Header [user]="user"></Header>
Функции также можно передавать как свойства.
<todoForm [addItem]="addItem"></todoForm>
События добавляются к компонентам с использованием синтаксиса скобок.
//in the todoForm.component.html file <form (ngSubmit)="addItem($event)"> <input [(ngModel)]="value" name="value" /> <input type="submit" value="Submit" /> </form>
Использование скобок и скобок приведет к двухсторонней привязке данных, привязанной к свойству состояния в todoComponent значения 'value'.
@Component({ selector: 'todoForm', templateUrl: './todoForm.component.html', }) export class TodoFormComponent { value = ''; @Input() addItem; }
При импорте свойств и функций используется тот же синтаксис, что и для вывода. Вы можете определить эти импорты в классе, как показано выше, или определить их в объекте Angular 2, как показано ниже.
@Component({ selector: 'todoForm', templateUrl: './todoForm.component.html', inputs: [addItem] }) export class TodoFormComponent { value = ''; }
Для тех, кто знаком с React, это также может сначала расстраивать. В React я бы просто деконструировал this.props в первой строке моего рендера. Вы можете пропустить этот шаг, но для удобства чтения я бы посоветовал вам этого не делать.
render() { let { user } = this.props; return ( <div className="Header"> <header user={user}></header> </div> ); }
Повсеместная тенденция при сравнении Angular 2 и React - Angular 2 требует, чтобы вы следовали соглашениям и гораздо более четко выражали свои намерения. Это можно объяснить тем фактом, что React - это скорее библиотека, чем фреймворк, что по своей сути означает, что он более гибкий.
Когда вы думаете об их целевой аудитории, это имеет смысл. Angular 1 захватил долю рынка, став одним из первых фреймворков, вышедших на рынок. Поскольку они защищают эту позицию (на процентной основе, а не на основе общего использования) для новичков, таких как emberJs, VueJs, Elm, вы поняли. Angular 2, на мой взгляд, создавался для тех первых пользователей, у которых теперь есть жизнеспособный бизнес, построенный на платформе. Явность при программировании становится все более и более важной по мере масштабирования, поэтому эти болевые точки, с которыми я сталкиваюсь с Angular 2, скорее всего, являются преднамеренными «лежачими полицейскими», призванными сэкономить время разработчиков в долгосрочной перспективе.
Angular 1 был чрезвычайно популярен, поэтому можно с уверенностью предположить, что Angular 2 будет видным фреймворком на долгие годы. Он почти в два раза быстрее, чем Angular 1, а это означает, что все компании, использующие Angular 1, скорее всего, перейдут на Angular 2. В противном случае им придется нанимать новых специалистов и перестраивать свое приложение с нуля.
Хотя мне не показался интуитивно понятный синтаксис, по причинам, упомянутым выше, я твердо верю, что изучение Angular 2 является обязательным условием для интерфейсного инженера, заботящегося о том, чтобы оставаться в курсе.