Ahora hay tres lĂderes claros entre los marcos en la interfaz: Angular, React y Vue. Creo que podemos juzgar el amor de los desarrolladores por el proyecto por el nĂşmero de estrellas en GitHub. En el momento de escribir este artĂculo, Vue ya tiene 161 mil estrellas , Reaccionar con 146 mil ocupa el segundo lugar y Angular con sus modestos 59.6 mil ocupa el tercer lugar .
A primera vista, puede parecer que Angular no es tan popular como otros marcos, pero si observamos los resultados de la investigaciĂłn estadĂstica del portal Tecla, veremos que Angular ocupa una cuota de mercado bastante grande. Por ejemplo, segĂşn un estudio, Angular se ejecuta en más de 400 mil sitios, mientras que Vue, en 100 mil. Propongo resolver esto. Considere por quĂ© los desarrolladores aman Vue, por quĂ© muchas aplicaciones están escritas en Angular y quĂ© beneficios puede obtener un desarrollador al usar el marco de Google especĂficamente para sĂ mismo.

Sobre el amor
Con mayor frecuencia, los siguientes elementos se destacan por la conveniencia especial de Vue (no se enumeran en orden de prioridad):
- Umbral de entrada bajo
- Tamaño del paquete
- ActuaciĂłn
- Componentes de archivo Ăşnico
- Sintaxis de plantilla simple
- Fácil expansión con complementos y módulos.
- 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:
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);
}
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>
<div class="click-place" [class.clicked]="clickCount > 0">
<button (click)="countUp()"> !</button>
<p *ngIf="clickCount > 0; else elseBlock">
: {{ clickCount }}
</p>
<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],
imports: [CommonModule],
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],
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 .
:
, , Vue. Angular 9 Ivy , , , . .