company_banner

Angular для Vue разработчиков

    Сейчас во фронтенде среди фреймворков есть три явных лидера: Angular, React и Vue. Думаю, мы можем судить о любви разработчиков к проекту по количеству звезд на GitHub. На момент написания данной статьи у Vue уже 161 тысяча звезд, на втором месте находится React с 146 тысячами, а на третьем месте — Angular со своими скромными 59.6 тысячами.


    С первого взгляда может показаться, что Angular не настолько популярный, как другие фреймворки, но если обратиться к результатам исследования статистики с портала Tecla, то мы увидим, что Angular занимает довольно большую долю рынка. Например, по данным исследования Angular работает на более чем 400 тысячах сайтов, в то время как Vue — на 100 тысячах. Предлагаю в этом разобраться. Рассмотрим, за что разработчики любят Vue, почему много приложений написаны на Angular и какие выгоды может получить разработчик при использовании фреймворка от Google конкретно для себя.



    Про любовь


    Чаще всего выделяют следующие пункты особенного удобства Vue (они перечислены не в порядке приоритета):


    • Низкий порог вхождения
    • Размер бандла
    • Производительность
    • Однофайловые компоненты
    • Простой синтаксис шаблонов
    • Простота расширения плагинами и модулями
    • Виртуальный DOM
    • Vue CLI
    • Вам не нужно задумываться о процессе рендеринга
    • Отличная документация на множестве языков

    Хотел бы обратить ваше внимание, что достаточно большая часть — это Developer Experience, то есть комфорт работы с фреймворком. Думаю, что теперь причина любви стала вполне очевидной. Если обобщить, то вы можете сесть, запустить vue-cli, сконфигурировать проект как вам нужно и сразу же начать делать классные вещи, не думая о рендеринге, оптимизации, сборке и многом другом.


    Но если работа с Vue — это сплошное удовольствие, то почему в больших компаниях Angular используется гораздо чаще? Когда одно из самых важных в разработке — это простота, комфорт и скорость, то тогда вам нужен Vue. Но когда речь заходит уже о крупном проекте с большим количеством разработчиков, сложной работой с данными и разнообразным API, то ситуация меняется. И давайте подробнее разберемся почему.


    Все уже решено


    Наверное, один из определяющих факторов при выборе фреймворка большой командой является наличие готовых подходов. Angular разработан таким образом, что для решения практически каждой проблемы уже существует какой-либо паттерн и готовая библиотека/сервис к нему. Предлагаю все рассматривать на примерах.


    В каждом SPA-приложении требуется работа с API. Как будет реализована работа в каждом из фреймворков?


    • Vue: собираемся командой и решаем что будем использовать. Нативный fetch или axios или что-то новое? Как будем обрабатывать ошибки? В каком месте будем отправлять запросы? Как будут называться классы? После того как вы решили и договорились — начали работать. Пришел новый сотрудник — ему нужно все это рассказать или составить документацию. Иногда новым разработчикам приходится доказывать, что ваше решение было лучшим на момент договоренности.
    • Angular: вы используете встроенный в Angular HttpClient, запросы отправляете из сервисов, которые работают с определенными сущностями. Классы будут носить стандартные названия, генерируемые Angular CLI. Обработку ошибок можно сделать в одном месте с помощью встроенного Interceptor. Приходит новый разработчик, и он ожидает, что все работает именно так.

    Стандарты и практики, принятые в сообществе Angular не только декларируют как писать хороший код, сохранять грамотную архитектуру, но и позволяют другим разработчикам быстро включаться в работу, понимать что происходит фактически с первого дня на проекте. Плюс, это избавляет вас от обсуждений внутри команды, которые практически со 100% вероятностью возникнут в проектах на Vue.


    Думаю, что это вообще один из основных плюсов подобных крупных решений — вам не нужно думать о части работы, вы можете потратить время на что-то другое (и это не обязательно работа). Итак, давайте рассмотрим что в Angular еще есть.


    Готовые паттерны


    Мы уже поговорили о сервисах, интерсепторах и клиенте для работы с API. Предлагаю рассмотреть что вы можете получить еще.


    Формы


    "Из коробки" во Vue работать с формами очень сложно. Вам нужно сформировать начальные данные, передать их в инпуты, ловить изменения и отражать их в данных. А если нужна валидация? Куда вы будете выводить ошибки? Как будете понимать, что форма еще не была "потрогана" пользователем? Да, есть классные сторонние библиотеки вроде Vuelidate. Но, вам как минимум нужно о них знать.


    В Angular “из коробки” реализована потрясающая работа с формами. Вы просто создаете FormGroup, передаете начальные значения, ставите нужные валидаторы и… Все. Далее вы можете управлять формой как угодно. Сбрасывать значения, ставить состояние dirty или принудительно указывать состояние валидности. То есть вам нужно думать исключительно о бизнес-логике.


    Dependency Injection


    DI — это механизм управления зависимостями, который выносит логику управления экземплярами из класса вовне. Можно сказать, что это самое важное отличие Angular от других фреймворков.


    Давайте представим, что у нас есть компонент, который выводит данные о пользователях социальной сети. Чтобы все было красиво, мы вынесем логику работы с API в специальный класс или функцию. В контексте Angular лучше выносить все в классы, поэтому мы создадим некий UserService. Теперь мы будем использовать наш сервис в коде компонента.


    Во Vue:


    • Если мы получаем данные только в одном месте, то можно просто создать экземпляр класса в компоненте.
    • Если нужно получить данные в нескольких компонентах, то можно сделать плагин, но тогда этот класс будет доступен повсеместно. Плюс, вам нужно знать о том, что этот плагин вообще существует.

    В Angular:


    При создании компонента в Angular вы просто указываете в конструкторе, что вам нужен UserService. После этого вы можете спокойно его использовать, не думая о лишних создаваемых экземплярах, о ленивой загрузке модулей и прочем. Если вам понадобится специальный экземпляр с определенными параметрами, то это тоже очень просто сделать.


    На самом деле, это довольно поверхностное описание работы механизма DI. Он позволяет очень удобно работать с зависимостями. Есть множество статей, которые описывают данный механизм, в том числе и моя. Если интересно, то можно ознакомиться.


    CLI


    CLI — это инструменты командной строки, которые помогают автоматизировать какой-либо процесс. Как правило, это типичные и даже рутинные задачи. Vue CLI позволяет быстро сконфигурировать и создать проект, а затем с его помощью собирать приложение, запускать тесты, линтеры и так далее. Но на этом его возможности заканчиваются. Так как в мире Vue нет уже готовых паттернов решения проблем, то и CLI не может его предложить.


    В мире Angular же CLI позволяет не только сконфигурировать и создать проект, но и сгенерировать сервисы, модули, компоненты, директивы и даже целые библиотеки. При создании компонента не только формируются все необходимые файлы, но и импортируются в нужные модули.


    Этот процесс происходит с помощью специальных библиотек-схематиков. При необходимости вы можете сами написать свой схематик с помощью специального мини-фреймворка. Например, вы можете написать свою библиотеку и использовать автоматическое создание корректных компонентов с принятыми в вашей организации правилами, генерировать автоматические файлы тестов или даже составлять базу для документации. Возможностей действительно масса.


    Angular CLI избавляет вас от массы рутинных операций, позволяя не думать о процессе создания файлов и прописывания импортов. Лучше потратьте сэкономленное время на архитектуру, отдых или на чтение Хабра.


    Базовая архитектура


    Давайте представим, что у нас есть приложение с довольно сложной бизнес-логикой. Во Vue нет строгих паттернов и поэтому вы можете поступать как хотите — вынести логику в специальные классы, в экшены стора или оставить ее прямо в компоненте.


    А в Angular уже начиная с обучения нам говорят, что компонент должен отвечать только за демонстрацию данных, а работа с ними должна происходить в сервисах. Это повышает чистоту и надежность кода, вносит ясность и упрощает понимание.


    В чем они похожи


    TypeScript


    TypeScript — это статически типизированный язык, "JavaScript that scales", как называют его создатели. Он привносит в JavaScript типы, позволяет писать красивые классы, как в "больших" языках программирования. О его возможностях и преимуществах в сравнении с JavaScript написано много статей и книг.


    Angular использует TypeScript по умолчанию, у вас просто нет возможности выбрать JavaScript или перейти на него вручную. Фреймворк использует множество конструкций TypeScript, без которых просто невозможно обойтись. Например декораторы, перечисления, интерфейсы и так далее.


    Vue также может работать с TypeScript. Более того, Vue CLI даже опционально предлагает выбрать TypeScript на этапе создания проекта. Единственным минусом является не совсем удобная реализация декораторов, вычисляемых значений и прочего. Например, вы можете указать свойства компонента или хуки жизненного цикла как в декораторе класса, так и в самом классе. Но это можно считать делом вкуса. Стоит также отметить, что TypeScript не заставляет вас писать компоненты в виде классов.


    Router


    На сегодняшний день сложно представить себе SPA-приложение без Lazy Loading'а. Если раньше мы реализовывали это с помощью Webpack'а, копались в его настройках и устанавливали плагины, то теперь фреймворки делают это за нас. Нам достаточно только написать одну конфигурацию.


    Для Vue существует библиотека Vue Router. Да, она поставляется отдельно, но тем не менее ее можно считать частью экосистемы Vue. Vue Router позволяет получить доступ к параметрам адреса, управлять навигацией, ставить классы для активных ссылок и многое другое.


    Angular имеет свой встроенный RouterModule, который позволяет делать все то же самое, но к тому же добавляет возможность отслеживать множество событий навигации (если быть точным, то 16), позволяет установить стратегию предзагрузки. В общем, имеет немного более широкий функционал.


    Observable


    Во Vue при обновлении значения в поле data автоматически происходит обновление связанных данных и перерисовка шаблона. Вам не нужно принудительно вызывать метод render() компонента или вообще как-то думать об этом процессе. Но как же это происходит?


    Здесь все просто — значения обновляются реактивно. Любое поле в данных — это Observer, то есть реализация паттерна "Наблюдатель". Давайте представим, что есть объект, у которого есть какое-то значение. И есть другие объекты, которые "наблюдают" за первым объектом. При изменении значения первого объекта наблюдатели узнают об этом и производят какие-то действия.


    Angular использует этот паттерн не только для отрисовки шаблона или обновления данных, но и вообще повсеместно. Он использует библиотеку для реактивного программирования RxJS, без которой также обойтись нельзя. Она позволяет представить любые операции с данными в поток. Все, что вам нужно сделать — это подписаться на этот поток данных и делать с результатом все, что захотите.


    Небольшой итог


    Давайте подведем итог и посмотрим что вы, как разработчик Vue, можете получить при работе с Angular:


    • Функционал "из коробки"
    • Готовые паттерны решения проблем
    • Быстрое включение других разработчиков в проект в контексте Angular
    • Экономию времени на обсуждениях за счет готовых решений и подходов
    • Мощный CLI

    Примеры


    А теперь я предлагаю реализовать компонент с одинаковым функционалом на Vue и Angular.


    Vue


    Давайте напишем простой пример с основными механизмами. В коде компонента ниже есть параметры, состояние, вычисляемые значения, хуки и методы — все, что требуется для нормальной работы.


    Код компонента


    <script>
    export default {
      name: 'HelloHabr',
      props: {
        name: {
          type: String,
          required: true,
          validator: value => value.trim().length !== 0,
        },
      },
      data() {
        return {
          clickCount: 0,
          secondsCount: 0,
          intervalId: null,
        };
      },
      computed: {
        clicksPerSecond() {
          if (this.secondsCount === 0) {
            return 0;
          }
    
          const DECIMAL = 1000;
          const ratio = this.clickCount / this.secondsCount;
    
          return Math.round(ratio * DECIMAL) / DECIMAL;
        },
      },
      created() {
        this.intervalId = setInterval(() => {
          this.secondsCount++;
        }, 1000);
      },
      beforeDestroy() {
        clearInterval(this.intervalId);
      },
      methods: {
        countUp() {
          this.$emit('updateClick', ++this.clickCount);
        },
      },
    };
    </script>
    

    Шаблон компонента


    <template>
      <div class="hello">
        <p>Привет, Хабр! Это {{ name }}.</p>
    
        <div class="click-place" :class="{ clicked: clickCount > 0 }">
          <button @click="countUp()">Кликни меня!</button>
          <p v-if="clickCount > 0">Общее количество кликов: {{ clickCount }}</p>
          <p v-else>Пока вы ни разу не кликнули</p>
        </div>
    
        <div class="statistic">
          <p>С момента открытия прошло {{ secondsCount }} секунд.</p>
          <p>Кликов в секунду: {{ clicksPerSecond }}</p>
        </div>
      </div>
    </template>

    Здесь мы также видим данные, обработку событий, динамические свойства и директивы.


    Использование компонента


    Чтобы использовать данный компонент, достаточно просто импортировать его в родителя:


    <script>
      import HelloHabr from './components/HelloHabr.vue';
    
      export default {
        name: 'App',
        components: { HelloHabr }
        ...
      };
    </script>

    Шаблон родителя будет выглядеть так:


    <template>
      <div id="app">
        <HelloHabr :name="name" @updateClick="updateClickCount" />
      </div>
    </template>

    Предлагаю реализовать такой же по функциональности компонент на Angular и посмотреть как он будет выглядеть.


    Angular


    Код компонента


    Код класса будет выглядеть так:


    import {
      Component,
      EventEmitter,
      Input,
      OnDestroy,
      OnInit,
      Output,
    } from '@angular/core';
    
    @Component({
      selector: 'hello-habr',
      templateUrl: './hello-habr.component.html',
      styleUrls: ['./hello-habr.component.less'],
    })
    // Указываем название класса и говорим какие интерфейсы он реализует.
    // В данном случае это необходимо, чтобы "напомнить" разработчику,
    // что компонент реализует указанные хуки жизненного цикла.
    export class HelloHabrComponent implements OnInit, OnDestroy {
      // Объявляем параметр компонента
      @Input() name: string;
    
      // Таким образом мы сообщаем наверх о событии
      @Output() updateClick = new EventEmitter<number>();
    
      // Состояние компонента
      clickCount = 0;
      secondsCount = 0;
      intervalId = null;
    
      // Хук компонента на момент инициализации
      ngOnInit() {
        this.intervalId = setInterval(() => {
          this.secondsCount++;
        }, 1000);
      }
    
      // Хук компонента на момент удаления
      ngOnDestroy() {
        clearInterval(this.intervalId);
      }
    
      // Геттер, который заменяет вычисляемое значение
      // Его логика работы отличается от Vue, но в текущем
      // примере данный вариант подходит
      get clicksPerSecond(): number {
        if (this.secondsCount === 0) {
          return 0;
        }
    
        const DECIMAL = 1000;
        const ratio = this.clickCount / this.secondsCount;
    
        return Math.round(ratio * DECIMAL) / DECIMAL;
      }
    
      // Метод компонента
      countUp() {
        this.updateClick.emit(++this.clickCount);
      }
    }

    Шаблон компонента


    Данному компоненту будет соответствовать следующий шаблон:


    <p>Привет, Хабр! Это {{ name }}.</p>
    
    <!-- В Angular можно указать едичный динамический класс -->
    <div class="click-place" [class.clicked]="clickCount > 0">
      <!-- Обработка событий примерно такая же, но без модификаторов  -->
      <button (click)="countUp()">Кликни меня!</button>
    
      <!-- Директивы, управляющие наличием DOM-элементов начинаются со звездочки -->
      <!-- else-блок нужно указать прямо в условии -->
      <p *ngIf="clickCount > 0; else elseBlock">
        Общее количество кликов: {{ clickCount }}
      </p>
      <!-- Сам else-блок выглядит немного иначе -->
      <ng-template #elseBlock><p>Пока вы ни разу не кликнули</p></ng-template>
    </div>
    
    <div class="statistic">
      <p>С момента открытия прошло {{ secondsCount }} секунд.</p>
      <p>Кликов в секунду: {{ clicksPerSecond }}</p>
    </div>

    Что касается компонента, то это все. В Angular есть целое множество возможностей переписать этот компонент по-другому. Например, используя потоки данных. Если интересно, то код компонента на потоках я представил ниже. На данном же этапе я хочу продемонстрировать схожее в двух фреймворках, поэтому реализовал все таким же образом, как и во Vue.


    Использование компонента


    В Angular используется модульная система. Модуль может включать в себя набор компонентов, сервисов или даже других модулей. Чтобы иметь возможность использовать компонент внутри модуля, достаточно его туда импортировать:


    import { NgModule } from '@angular/core';
    import { AppComponent } from './app.component';
    import { HelloHabrComponent } from './hello-habr/hello-habr.component';
    
    @NgModule({
      // Здесь мы указываем, что компонент используется в модуле
      declarations: [AppComponent, HelloHabrComponent],
      imports: [BrowserModule],
      providers: [],
      bootstrap: [AppComponent],
    })
    export class AppModule {}

    В данном примере у нас есть главный модуль, и мы просто говорим, что используем новый компонент здесь. Он будет доступен для указания в шаблоне AppComponent.


    Но есть и другой способ. Например, наш компонент использует другие модули. Чтобы не импортировать все в AppModule, мы создаем специальный модуль и импортируем компонент уже в него. Чтобы компонент стал доступен вне модуля, нужно его экспортировать. Выглядит это так:


    import { NgModule } from '@angular/core';
    import { CommonModule } from '@angular/common';
    import { HelloHabrComponent } from './hello-habr.component';
    
    @NgModule({
      // Так же указываем, что компонент используется в модуле
      declarations: [HelloHabrComponent],
      // CommonModule позволяет использовать директивы вроде *ngIf
      imports: [CommonModule],
      // Делаем его доступным вне модуля HelloHabrModule
      exports: [HelloHabrComponent],
    })
    export class HelloHabrModule {}

    После того, как мы подготовили наш модуль, его достаточно просто импортировать туда, где мы его будем использовать:


    import { BrowserModule } from '@angular/platform-browser';
    import { NgModule } from '@angular/core';
    
    import { AppComponent } from './app.component';
    import { HelloHabrModule } from './hello-habr/hello-habr.module';
    
    @NgModule({
      declarations: [AppComponent],
      // Импортируем модуль и можем использовать "HelloHabrComponent"
      imports: [BrowserModule, HelloHabrModule],
      providers: [],
      bootstrap: [AppComponent],
    })
    export class AppModule {}

    Такой способ работы позволяет инкапсулировать всю специальную логику в одном месте и при импорте не думать об этом. Плюс, разделение на модули позволяет удобно управлять Lazy-Loading'ом.


    В шаблоне родителя использование компонента вне зависимости от реализации декларации будет выглядеть одинаково:


    <hello-habr [name]="name" (updateClick)="updateClickCount($event)"></hello-habr>

    Код компонента на потоках


    Вот как можно реализовать тот же самый компонент, но уже на потоках:


    import { Component, EventEmitter, Input, Output } from '@angular/core';
    import { BehaviorSubject, combineLatest, interval } from 'rxjs';
    import { map, startWith } from 'rxjs/operators';
    
    @Component({
      selector: 'hello-habr',
      templateUrl: './hello-habr.component.html',
      styleUrls: ['./hello-habr.component.less'],
    })
    export class HelloHabrComponent {
      @Input() name: string;
      @Output() updateClick = new EventEmitter<number>();
    
      clicksCount$ = new BehaviorSubject<number>(0);
    
      secondsCount$ = interval(1000).pipe(
        map(second => second++),
        startWith(0)
      );
    
      clicksPerSecond$ = combineLatest(this.clicksCount$, this.secondsCount$).pipe(
        map(([clicks, seconds]) => this.getClicksPerSecond(clicks, seconds))
      );
    
      countUp() {
        const newValue = this.clicksCount$.value + 1;
    
        this.updateClick.emit(newValue);
        this.clicksCount$.next(newValue);
      }
    
      private getClicksPerSecond(
        clicksCount: number,
        secondsCount: number
      ): number {
        if (secondsCount === 0) {
          return 0;
        }
    
        const DECIMAL = 1000;
        const ratio = clicksCount / secondsCount;
    
        return Math.round(ratio * DECIMAL) / DECIMAL;
      }
    }

    В данном примере все считается декларативно. Что это нам дает:


    • Не нужно вручную запускать интервал и отслеживать его остановку при удалении компонента. Это за нас сделает Angular.
    • Не нужно завязываться на хуки жизненного цикла компонента.
    • Нет лишних перерисовок шаблона. В нашей старой схеме на каждое изменение переменной класса запускался механизм проверки наличия изменений. В текущей же схеме компонент будет обновляться только при изменениях данных в потоках. Это не сильно заметно, так как мы обновляем шаблон каждую секунду. Но если убрать строчку с секундами, то разница будет очевидной.
    • Мы немного сократили количество кода и сделали его более читаемым для тех, кто знаком с потоками данных.

    Итог


    Итак, давайте подведем итог. Почему большие проекты, скорее всего, будет удобнее писать на Angular:


    • Готовые паттерны решения проблем.
    • Множество функционала доступно из коробки: роутер, формы и их валидация, перехватчики (interceptors), клиент для работы с запросами и многое другое.
    • Мощный CLI, который позволяет не только создавать и запускать проект, но и создавать файлы, корректно выставлять зависимости и так далее.
    • Dependency Injection — механизм управления зависимостями.
    • RxJS и TypeScript по умолчанию.

    Что вы можете получить как разработчик:


    • Экономию времени на обсуждениях и спорах.
    • Экономию времени на изобретении велосипедов.
    • Возможность быстро включиться в процесс разработки на Angular практически в любой команде.

    Стоит также отметить, что вы не лишаетесь всех плюсов, что есть в работе со Vue. В Angular 9 благодаря новому движку Ivy разработка идет так же быстро, дебаг стал более удобным, размер бандла стал еще меньше, а процесс рендеринга работает еще быстрее за счет нового механизма. Поэтому просто могу порекомендовать вам попробовать.

    Tinkoff.ru
    IT’s Tinkoff.ru — просто о сложном

    Комментарии 32

      –11
      Написать на КПДВ — VueJS — 156 кВ, Angular — 56 kb — это по вашему честно? Я считаю это вранье. Вы даже не потрудились объяснить при каких условиях появились такие цифры.
      Ну нравится вам Angular, нет вопросов. А зачем теперь про другие фреймворки всякие байки распускать?

      Вот на вскидку первый же попавшийся материал на эту тему — Sizes of JS frameworks:

      mber 2.2.0 435K
      Ember 1.13.8 486K
      Angular 2 566K
      Angular 2 + Rx 766K
      Angular 1.4.5 143K
      Vue 2.4.2 58.8K
      Inferno 1.2.2 48K
      Preact 7.2.0 16K
      React 0.14.5 + React DOM 133K
      React 0.14.5 + React DOM + Redux 139K
      React 16.2.0 + React DOM 97.5K

      И читать ваш код даже расхотелось, там наверное тоже наманипулировали.
        +7

        Это не вес, а количество звезд на GitHub). На самом деле, мне нравится и Vue и Angular.
        Я не топлю за определенный фреймворк и не стараюсь "обратить в свою веру". Просто рассказываю что вы можете получить при переходе на Angular. Разумеется, у Vue есть свои плюсы, я говорю о них в самом начале статьи.

        –1
        Ни слова про Vuex. Первые 5 пунктов в итогах есть и в Vue, последующие так же высосаны из пальца. С Vue интересен был бы переход на AngularDart, но про этот плюс вы забыли.
          0

          Vuex — это отдельный пакет для управления состоянием, во Vue его по умолчанию нет. В Angular ничего такого тоже нет, потому я про это ничего не написал. Расскажите пожалуйста про первые 5 пунктов во Vue. Разве это есть "из коробки"? Я хотел особенно подчеркнуть, что в Angular уже это все есть, на этом основана архитектура и паттерны решения проблем. Все это ведет к общим практикам.

            +3
            Из коробки в моем понимании, то что поддерживается сообществом и можно поставить, настроить в течении 3-5 минут. А вот пихать все что нужно и не нужно в сборку, по мне так это как раз плохая практика.
              +1

              В таком случае вопрос переходит в другой разряд. Типа Vue и Angular со всеми возможностями. Vuex и NgRx и другое. Вообще я не вижу смысла делать такое сравнение. Хотел просто показать что можно получить "на базовом уровне".

                +1
                То есть вы не видите смысла делать объективное сравнение. Vuex вполне себе официальная библиотека о чем сказано в документации:
                vuejs.org/v2/guide/state-management.html
                  +1

                  Сравнить официальную библиотеку для Vue с неофициальной для Angular? Звучит не очень логично. По умолчанию в Angular предлагается хранить данные в сервисах, а не в Store. Если сравнивать в принципе два подхода, то это тема для отдельной статьи, но и тут я смысла особого не вижу. Нужно пользоваться тем, что удобно в вашем случае. Даже если я "докажу", что один подход более эффективен, то это же не будет причиной переходить на новый фреймворк, верно?

                    +1
                    На мой взгляд Vue и Angular ~+- одинаковые, из статьи хотелось почерпнуть существенные плюсы, но их не нашел. На данном этапе развития обоих фреймворков, выбор того или иного скорее просто дело вкуса.
                    0
                    Тогда можно Angular Material и Angular CDK к Ангуляру приписать, как «из коробки» )
                      +1
                      У Vue есть Vuetify, на том же Material.
            +1
            С ангуляром есть одна особенность — вы будете программистом на ангуляре. В смысле как «вы будете программистом 1С» (никого не хочу обидеть): язык составляет малую долю от знаний необходимых соглашений, декораторов, структур и приёмов. Да, быстро. Да, эффективно. Если не нужно что-то такое, о чём разработчики ангуляра не подумали за вас. И да, если вы развиваетесь так, как они придумали и всегда можете объяснить бизнесу «вот эта штучка противоречит политике фреймворка, так что нет». Очень удобно для фулстека, кстати, где фронт всё же на вторых ролях.

            Усреднённый энтерпрайз с гарантированым средним уровнем.

            Это не хорошо и не плохо, это особенность.

            ЗЫ Ну и, мне кажется, не стоит всё же сравнивать фреймворк с библиотеками.
              +3

              Здесь не могу согласиться. Да, конечно, Angular реализуют бОльшую часть логики приложения, но это не значит, что вы не должны разбираться как работают классы и те же декораторы. У меня есть много коллег, которые пишут много классных вещей на Angular и для Angular, например https://habr.com/ru/users/waterplea/posts/. Для этого необходимо не только хорошее знание и понимание фреймворка, но и самого языка.


              Отдельно хотел бы сказать, что Angular реализует множество паттернов, применимых в принципе к программированию, например, Dependency Injection. Поэтому, Angular может принести пользу не только во фронтенде.

                +4
                Не соглашусь.
                Angular предоставляет инструменты реализующие общепринятные паттерны.
                Если приглядеться, то Angular очень похож на тот же Spring boot из java.
                Конечно, если нормально не изучив язык программирования сразу браться за angular, то знать будешь только angular.
                Но если хорошо знать основы ЯП, паттерны проектирования, структуры данных, алгоритмы, тогда любые фреймворки/библиотеки не будут вызывать сложностей в изучении и понимании.
                  +1

                  Не соглашусь.


                  У обычного человека есть время что-то изучать только на работе. Ты узнаешь что-то новое тогда и только тогда, когда на работе появится задачка, требующая изучения. Дома, ясное дело, остается времени сгонять катку в доту, поесть и поспать.


                  Поэтому очень-очень хорошо, когда на работе сама жизнь заставляет пробовать тебя сотни фреймворков и переписывать много раз одно и то же с разными подходами. Это получается полноценное непрерывное обучение — и тебе за него платят деньги! Если же есть какой-то условный 1С, где всё уже придумано, то жизнь может превратиться в непрерывную деградацию.


                  Понятно, что часов у тебя в любом случае 8, и значит развиваться ты всё-таки будешь — но в каком-то другом деле. Например, в бизнес-области: работая в банке будешь глубоко разбираться в банковской сфере и слабо — в низкоуровневом программировании и создании фреймворков.


                  Лично я всю жизнь (ту ее часть, когда хотел расти как программист) очень хотел заниматься именно разработкой инструментов для программистов, написанием фреймворков, итп — и ни в коем случае не конечных продуктов. В крайнем случае, разработкой архитектур продуктов. Конечные продукты — это скучно. Использование полностью готового фреймворка не кажется хорошей идеей в этой концепции, потому что на работе ты слишком много времени будешь уделять вещам, которые тебя никак не развивают.

                    +1
                    У обычного человека есть время что-то изучать только на работе.

                    Не соглашусь, у меня и у моих коллег находится время изучать новое и еще писать статьи :)

                    Дома, ясное дело, остается времени сгонять катку в доту, поесть и поспать.

                    У всех разные увлечения, я в доту не играю.

                    потому что на работе ты слишком много времени будешь уделять вещам, которые тебя никак не развивают

                    Жаль, что у вас сложился такой опыт.
                    Я сам стараюсь развиваться и в рабочее и вне рабочего времени, как и мои коллеги.

                    Итого, люди разные, с разными возможностями и мотивацией, так что не стоит под «обычных людей» подписывать всех, кто не имеет возможности развиваться на работе и у кого нет желания развиваться вне работы.
                  +1
                  Ангуляр очень близок к нативным веб компонентам по принципу работы, так что не соглашусь тоже. Большая часть хороших практик работы с Ангуляром актуальна для всего с компонентным уклоном.
                    0
                    Очень интересное утверждение. Не могли бы Вы его обосновать? Просто у меня есть некоторый практический опыт с ангуляром (1.2-9), реактом, вью и вебкомпонентами, и я бы так не стал утверждать.
                      0
                      Ну разделение на изолированные компоненты с входными данными, инкапсуляция стилей, то, как лучше всего внутреннюю организацию компонентов сделать, шаблоны и кастомизация внешнего вида. Я работаю над библиотекой UI компонентов и если добавить в веб компоненты DI и проверку изменений, то практически всё, что я делаю можно без особого труда в них перенести не сильно меняя код.

                      У меня, тогда, встречный вопрос:
                      Если не нужно что-то такое, о чём разработчики ангуляра не подумали за вас. И да, если вы развиваетесь так, как они придумали и всегда можете объяснить бизнесу «вот эта штучка противоречит политике фреймворка, так что нет»

                      Можете привести пример штук, противоречащих политике фреймворка? Я бы сказал, чо разработчики Ангуляр подумали за нас только в очень глобальных вопросах, скажем, в роутинге, в остальных же случаях они оставили нам полную свободу действий и я не могу сходу назвать ситуацию, которую вы озвучили.
                        0
                        Я работаю над библиотекой UI компонентов и если добавить в веб компоненты DI и проверку изменений, то практически всё, что я делаю можно без особого труда в них перенести не сильно меняя код.


                        Ага, понятно. Если заниматься задачами такого рода, то да, действительно здорово похоже. Я имел в виду обычную, «дженерик» разработку — мидлов, клепающих формы в рамках предустановленной архитектуры.

                        Впрочем, заранее соглашусь, что если человеку не интересно, что там внутри и почему, то среда не важна (и ангуляр тут в плюс, потому что не даёт совсем уж наговнокодить).

                        Противоречащие штуки — да пожалуйста. Мне нужен кастомный билд конвеер (он есть, он не работает так, как нужно). Мне нужен свой роутинг, свой бандлинг и свой бутстраппинг. Не от хорошей жизни, поверьте.

                        Да, не типовые случаи — ну я и сказал, что для типовых обычно есть типовое решение.
                          0
                          Буду рад подсказать, если что-то знаю, если опишешь подробнее почему это нужно. Если, конечно, хочется это обсудить )
                            0
                            Там вряд ли чем-то можно помочь =) сложный сетап, большой проект с 12+ годами истории. Я когда с разработчиками ангуляра общался на конференциях, так реакция была «нифига себе, что людям бывает нужно! мы даже не думали, что такое бывает! ну вы и извращенцы (шутка)»

                            Но спасибо.
                    0
                    Если нужно что-то такое, то берешь и пишешь, точно так же, как и в любом другом фреймворке.
                    Никаких «я пишу на Angular» тут нет. Это тот же самый js, только обычно мы работаем с ним через абстракции фреймворка, но всегда есть возможность сделать напрямую, а лучше написать свою абстракцию.
                    0
                    Для Vue есть Class Component Decorator
                      +2
                      Лично я восхищен Vue DevTools инструментарием плюс ко всему...imho про популярность Angular это как про Java. Legacy, legacy, legacy.
                        0
                        Ты не путаешь с AngularJS? :)
                        0
                        Имхо в статье не отмечен момент «магии реактивности» Vue. Когда ее становится слишком много то будет больно.
                        Мне нравится, что в Angular я могу контролировать эти вещи, в том числе и притащить такую же магию, впрочем в React можно так же.
                          0
                          А как сделать слишком много? Не обязательно же все данные держать в data, плюс объекты можно замораживать.
                          +1

                          Хотел бы написать свое мнение на данную статью, на мой взгляд весьма однобокую в сторону Angular
                          Просто момент бросившийся в глаза, во Vue тоже так можно сделать? От чего такое акцентирование на angular?


                          <!-- В Angular можно указать едичный динамический класс -->

                          По статье создается впечатление, что чем больше ограничивают разработчика и больше впихнут в проект тем лучше(не хейт angular, nestjs на его основе шикарен).


                          По пунктам итога:


                          1. Не используя angular не могу говорить конкретики насколько это нужно и оправдано не разделяя пакеты
                          2. vue-router можно считать из коробки(как и vuex, о котором ни слова, но о фичах angular типа форм информация есть), формы не поспорю +очко ang, перехватчики и httpclient, субьективно не вижу смысла ограничивать разработчика, тот же axios(который используется в большинстве проектов) имеет и функцию перехватчиков и поддерживается огромным кол-вом людей
                          3. Плагины к vue-cli если не ошибаюсь могут в том числе расширить функционал и до такого(хотя критичной нужды не вижу), но опять же, не преувеличенно ли значение создания файла с шаблонным контентом?
                          4. Много ли кейсов которые не покрываются весьма простыми асинхронными vue-компонентами? Для store, есть аналог в виде динамических модулей
                          5. Если RxJs обязателен для использования, опять же навязывание технологий, typescript, с ним у vue < 3.0 проблемы не поспорю, что он обязателен в angular, ну качество кода по-умолчанию будет выше, хотя порог вхождения новичкам тоже выше, поэтому +-
                          6. Стандарты решают проблему
                          7. Использование готовых решений для конкретной задачи решает проблему(минус — нужно время искать решения)
                          8. Стандарты решают проблему
                            0

                            Хотел бы обратить внимание, что я не топлю за Angular. Я предлагаю Vue разработчикам рассмотреть что они могут получить, если перейдут на него. Например, они хотят пойти в Google и писать фронт там. У меня не было цели сравнить фреймворки, а скорее показать различия, чтобы было проще и быстрее понять принципы работы Angular.

                            +1

                            Для меня одним из плюсов ангуляр является то что после него легко писать на Nestjs. Более того, он добавляется в проект одним кликом

                              0
                              Геттер, который заменяет вычисляемое значение. Его логика работы отличается от Vue
                              Вы тут умолчали о том, что в примере на Vue у вас есть мемоизация и автоматическое вычисление зависимостей (благодаря Transparent Reactive Programming). В примере на Angular функция будет пересчитываться на каждый вызов Change Detection, что гораздо менее эффективно. Не говоря уже о том, что во Vue вам не нужно делать подписку на интервал вне Zone.js, а в Angular вы рано или поздно столкнётесь с необходимостью так делать. Я как-то добавлял таймер обратного отсчёта в Angular приложение, таймер был вверху дерева компонентов и на каждый тик триггерил CD рекурсивно у всех компонентов ниже. Тут ещё спасает OnPush, но во Vue это не нужно.
                              Он использует библиотеку для реактивного программирования RxJS, без которой также обойтись нельзя.
                              Без RxJS можно прекрасно обойтись даже в Angular, посмотрите например Mobx-Angular. Я был на проекте, который писали фулстеки с уклоном в бекенд, и им было очень тяжело совладать с RxJS и его операторами, в коде были все возможные антипаттерны RxJS — вложенные подписки, отсутствие отписок, непонимание разницы между switchMap/mergeMap/concatMap и как следствие трудновоспроизводимые баги. Mobx зашёл на ура разработчикам из-за привычной модели программирования, писать код стало проще. Ну и вот возьмём ваш пример на RxJS, в нём ведь тоже есть проблемы:
                              — Лишний BehaviorSubject. Вместо того, чтобы считать количество кликов через оператор scan вы ввели состояние, которое мутируете вручную. Это императивный подход. Такой код люди пишут постоянно, потому что ломать голову операторами RxJS сложно.
                              — Подписка на интервал в шаблоне у вас скорее всего через async pipe, а это опять будет триггерить CD на каждый тик. На интервалы/таймеры нужно подписываться вне Zone.js

                              Вся эта ненужная сложность, отсутствие девтулзов и ещё вагон проблем с типизацией (она в Angular слишком щадящая) и побудили меня отказаться от этого фреймворка в пользу React.

                              Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                              Самое читаемое