Mais conteúdo relacionado Semelhante a Паразитируем на React-экосистеме (Angular 4+) / Алексей Охрименко (IPONWEB) (20) Паразитируем на React-экосистеме (Angular 4+) / Алексей Охрименко (IPONWEB)7. import { Component } from '@angular/core';
@Component({
moduleId: module.id,
selector: 'project-name-app',
template: `
<h1 (click)='onClick()'>
{{title}}
</h1>
`,
styleUrls: ['project-name.component.css']
})
export class PROJECTNAMEAppComponent {
title = 'project-name works!';
}
8. import { Component } from '@angular/core';
@Component({
moduleId: module.id,
selector: 'project-name-app',
template: `
<h1 (click)='onClick()'>
{{title}}
</h1>
`,
styleUrls: ['project-name.component.css']
})
export class PROJECTNAMEAppComponent {
title = 'project-name works!';
}
9. import { Component } from '@angular/core';
@Component({
moduleId: module.id,
selector: 'project-name-app',
template: `
<h1 (click)='onClick()'>
{{title}}
</h1>
`,
styleUrls: ['project-name.component.css']
})
export class PROJECTNAMEAppComponent {
title = 'project-name works!';
}
12. Паразитизм
• форма взаимоотношений между организмами различных
видов, из которых один (паразит — aka Angular 4+)
использует другого (хозяина — aka React) в качестве среды
обитания и источника питания, нанося ему вред, но при
этом не убивая.
13. Паразитоид
• организм, который проводит значительную часть своей
жизни (в личиночной стадии), проживая на или внутри
своего единственного хозяина, которого он постепенно
убивает в процессе.
14. Паразитоид
• организм, который проводит значительную часть своей
жизни (в личиночной стадии), проживая на или внутри
своего единственного хозяина, которого он постепенно
убивает в процессе.
16. + + + + + + + + + +
• RxJs -> Observable
17. + + + + + + + + + +
• RxJs -> Observable
• поддержка Immutable структур данных
18. + + + + + + + + + +
• RxJs -> Observable
• поддержка Immutable структур данных
• Denendency Injection
19. + + + + + + + + + +
• RxJs -> Observable
• поддержка Immutable структур данных
• Denendency Injection
• нет необходимости ничего Angular-ифаить, оборачивать и
адаптировать
20. + + + + + + + + + +
• RxJs -> Observable
• поддержка Immutable структур данных
• Denendency Injection
• нет необходимости ничего Angular-ифаить, оборачивать и
адаптировать
• Многопоточность с WebWorkers
31. SSR (Universal App) - EASY MODE
https://github.com/angular/angular-cli
https://github.com/evertonrobertoauler/cli-
universal-demo
47. CLI
npm install -g create-react-app
create-react-app PROJECT-NAME
cd PROJECT-NAME/
npm start
npm install -g @angular/cli
ng new PROJECT-NAME
cd PROJECT-NAME/
ng serve
48. Angular/CLI - Scaffolding
Component
ng g component my-new-
component
Directive
ng g directive my-new-
directive
Pipe
ng g pipe my-new-pipe
Service
ng g service my-new-
service
Class
ng g class my-new-class
Guard
ng g guard my-new-guard
Interface
ng g interface my-new-
interface
Enum
ng g enum my-new-enum
Module
ng g module my-module
55. Redux
interface IAppState { /* ... */ };
export const store: Store<IAppState> = createStore(
rootReducer,
applyMiddleware(createLogger())
);
56. Redux
interface IAppState { /* ... */ };
export const store: Store<IAppState> = createStore(
rootReducer,
applyMiddleware(createLogger())
);
57. Redux
interface IAppState { /* ... */ };
export const store: Store<IAppState> = createStore(
rootReducer,
applyMiddleware(createLogger())
);
60. Redux
import { select } from '@angular-redux/store';
@Component({
template: '<button (click)="onClick()">Clicked {{ count | async }} times</button>'
})
class App {
@select() count$: Observable<number>;
constructor(private ngRedux: NgRedux<IAppState>) {}
onClick() {
this.ngRedux.dispatch({ type: INCREMENT });
}
}
61. Redux
import { select } from '@angular-redux/store';
@Component({
template: '<button (click)="onClick()">Clicked {{ count | async }} times</button>'
})
class App {
@select() count$: Observable<number>;
constructor(private ngRedux: NgRedux<IAppState>) {}
onClick() {
this.ngRedux.dispatch({ type: INCREMENT });
}
}
62. Redux
import { select } from '@angular-redux/store';
@Component({
template: '<button (click)="onClick()">Clicked {{ count | async }} times</button>'
})
class App {
@select() count$: Observable<number>;
constructor(private ngRedux: NgRedux<IAppState>) {}
onClick() {
this.ngRedux.dispatch({ type: INCREMENT });
}
}
63. Redux
import { select } from '@angular-redux/store';
@Component({
template: '<button (click)="onClick()">Clicked {{ count | async }} times</button>'
})
class App {
@select() count$: Observable<number>;
constructor(private ngRedux: NgRedux<IAppState>) {}
onClick() {
this.ngRedux.dispatch({ type: INCREMENT });
}
}
64. Redux
import { select } from '@angular-redux/store';
@Component({
template: '<button (click)="onClick()">Clicked {{ count | async }} times</button>'
})
class App {
@select() count$: Observable<number>;
constructor(private ngRedux: NgRedux<IAppState>) {}
onClick() {
this.ngRedux.dispatch({ type: INCREMENT });
}
}
69. Mobx
import {store} from './store/counter';
@Component({
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<div *mobxAutorun>
{{ store.value }} - {{ store.computedValue }}
<button (click)="store.action">Action</button>
</div>
`
})
export class AppComponent {
store = store;
}
70. Mobx
import {store} from './store/counter';
@Component({
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<div *mobxAutorun>
{{ store.value }} - {{ store.computedValue }}
<button (click)="store.action">Action</button>
</div>
`
})
export class AppComponent {
store = store;
}
71. Mobx
import {store} from './store/counter';
@Component({
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<div *mobxAutorun>
{{ store.value }} - {{ store.computedValue }}
<button (click)="store.action">Action</button>
</div>
`
})
export class AppComponent {
store = store;
}
72. Mobx
import {store} from './store/counter';
@Component({
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<div *mobxAutorun>
{{ store.value }} - {{ store.computedValue }}
<button (click)="store.action">Action</button>
</div>
`
})
export class AppComponent {
store = store;
}
73. Mobx
import {store} from './store/counter';
@Component({
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<div *mobxAutorun>
{{ store.value }} - {{ store.computedValue }}
<button (click)="store.action">Action</button>
</div>
`
})
export class AppComponent {
store = store;
}
74. Mobx
import {store} from './store/counter';
@Component({
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<div *mobxAutorun>
{{ store.value }} - {{ store.computedValue }}
<button (click)="store.action">Action</button>
</div>
`
})
export class AppComponent {
store = store;
}
75. Mobx
import {store} from './store/counter';
@Component({
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<div *mobxAutorun>
{{ store.value }} - {{ store.computedValue }}
<button (click)="store.action">Action</button>
</div>
`
})
export class AppComponent {
store = store;
}
81. GraphQL
import { ApolloClient } from 'apollo-client';
import { ApolloModule } from 'apollo-angular';
const client = new ApolloClient();
export function provideClient(): ApolloClient {
return client;
}
82. GraphQL
import { ApolloClient } from 'apollo-client';
import { ApolloModule } from 'apollo-angular';
const client = new ApolloClient();
export function provideClient(): ApolloClient {
return client;
}
83. GraphQL
import { ApolloClient } from 'apollo-client';
import { ApolloModule } from 'apollo-angular';
const client = new ApolloClient();
export function provideClient(): ApolloClient {
return client;
}
87. GraphQL
// We use the gql tag to parse our query string into a query
document
const CurrentUserForProfile = gql`
query CurrentUserForProfile {
currentUser {
login
avatar_url
}
}
`;
88. GraphQL
@Component({ ... })
class ProfileComponent implements OnInit {
constructor(private apollo: Apollo) {}
ngOnInit() {
this.apollo.watchQuery<QueryResponse>({
query: CurrentUserForProfile
}).subscribe(({data}) => {
this.loading = data.loading;
this.currentUser = data.currentUser;
});
}
}
89. GraphQL
@Component({ ... })
class ProfileComponent implements OnInit {
constructor(private apollo: Apollo) {}
ngOnInit() {
this.apollo.watchQuery<QueryResponse>({
query: CurrentUserForProfile
}).subscribe(({data}) => {
this.loading = data.loading;
this.currentUser = data.currentUser;
});
}
}
90. GraphQL
@Component({ ... })
class ProfileComponent implements OnInit {
constructor(private apollo: Apollo) {}
ngOnInit() {
this.apollo.watchQuery<QueryResponse>({
query: CurrentUserForProfile
}).subscribe(({data}) => {
this.loading = data.loading;
this.currentUser = data.currentUser;
});
}
}
91. GraphQL
@Component({ ... })
class ProfileComponent implements OnInit {
constructor(private apollo: Apollo) {}
ngOnInit() {
this.apollo.watchQuery<QueryResponse>({
query: CurrentUserForProfile
}).subscribe(({data}) => {
this.loading = data.loading;
this.currentUser = data.currentUser;
});
}
}
99. Способы выражения логики в
шаблонах Angular
• Структурные директивы
• Pipes
• Свои структурные директивы
• ViewModel + Структурные директивы
102. Article List (не нужен)
<article-preview
*ngFor="let article of results"
[article]="article">
</article-preview
103. Pipes
<article-preview
*ngFor="let article of (results | intrestingArticles)"
[article]="article">
</article-preview>
@Pipe({ name: 'intrestingArticles' })
export class ArticlesPipe implements PipeTransform {
transform(items: any[]) {
return items.filter(item => item.intresting);
}
}
104. Pipes
<article-preview
*ngFor="let article of (results | intrestingArticles)"
[article]="article">
</article-preview>
@Pipe({ name: 'intrestingArticles' })
export class ArticlesPipe implements PipeTransform {
transform(items: any[]) {
return items.filter(item => item.intresting);
}
}
105. Pipes
<article-preview
*ngFor="let article of (results | intrestingArticles)"
[article]="article">
</article-preview>
@Pipe({ name: 'intrestingArticles' })
export class ArticlesPipe implements PipeTransform {
transform(items: any[]) {
return items.filter(item => item.intresting);
}
}
106. Pipes
<article-preview
*ngFor="let article of (results | intrestingArticles)"
[article]="article">
</article-preview>
@Pipe({ name: 'intrestingArticles' })
export class ArticlesPipe implements PipeTransform {
transform(items: any[]) {
return items.filter(item => item.intresting);
}
}
107. Свои структурные директивы
@Directive({
selector: '[appDelay]'
})
export class DelayDirective {
constructor(
private templateRef: TemplateRef<any>,
private viewContainerRef: ViewContainerRef
) { }
@Input()
set appDelay(time: number): void { }
}
108. Свои структурные директивы
@Directive({
selector: '[appDelay]'
})
export class DelayDirective {
constructor(
private templateRef: TemplateRef<any>,
private viewContainerRef: ViewContainerRef
) { }
@Input()
set appDelay(time: number): void { }
}
109. Свои структурные директивы
@Directive({
selector: '[appDelay]'
})
export class DelayDirective {
constructor(
private templateRef: TemplateRef<any>,
private viewContainerRef: ViewContainerRef
) { }
@Input()
set appDelay(time: number): void { }
}
110. Свои структурные директивы
@Directive({
selector: '[appDelay]'
})
export class DelayDirective {
constructor(
private templateRef: TemplateRef<any>,
private viewContainerRef: ViewContainerRef
) { }
@Input()
set appDelay(time: number): void { }
}
116. ViewModel + Структурные директивы
https://www.youtube.com/watch?v=WIgXOG49mdI
"Изоморфный D3 + MALEVICH", Алексей Охрименко, MoscowJS 25
https://github.com/aiboy/COD.js
onUpdate(data) {
this.fire('update', data.map((item) => {
return { id: item, selected: item === this.selectedItemId }
}));
this.data = data;
}
onItemSelected(id) {
this.selectedItemId = id;
this.onUpdate(this.data);
}
117. ViewModel + Структурные директивы
https://www.youtube.com/watch?v=WIgXOG49mdI
"Изоморфный D3 + MALEVICH", Алексей Охрименко, MoscowJS 25
https://github.com/aiboy/COD.js
onUpdate(data) {
this.fire('update', data.map((item) => {
return { id: item, selected: item === this.selectedItemId }
}));
this.data = data;
}
onItemSelected(id) {
this.selectedItemId = id;
this.onUpdate(this.data);
}
118. ViewModel + Структурные директивы
https://www.youtube.com/watch?v=WIgXOG49mdI
"Изоморфный D3 + MALEVICH", Алексей Охрименко, MoscowJS 25
https://github.com/aiboy/COD.js
onUpdate(data) {
this.fire('update', data.map((item) => {
return { id: item, selected: item === this.selectedItemId }
}));
this.data = data;
}
onItemSelected(id) {
this.selectedItemId = id;
this.onUpdate(this.data);
}
119. ViewModel + Структурные директивы
https://www.youtube.com/watch?v=WIgXOG49mdI
"Изоморфный D3 + MALEVICH", Алексей Охрименко, MoscowJS 25
https://github.com/aiboy/COD.js
onUpdate(data) {
this.fire('update', data.map((item) => {
return { id: item, selected: item === this.selectedItemId }
}));
this.data = data;
}
onItemSelected(id) {
this.selectedItemId = id;
this.onUpdate(this.data);
}