SlideShare a Scribd company logo
1 of 99
Download to read offline
Angular 2 не так уж
и плох,
а если задуматься то и просто хорош.
Алексей Охрименко ( IPONWEB )
1
Здоровье прежде всего
2
Алексей
Охрименко
Tweeter: @Ai_boy
Gitter: aiboy
3
IPONWEB
4
5
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!';
}
6
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!';
}
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!';
}
Глава №1 - И была рука
8
KSS
9
KSS
10
Babel
KSS
11
TypeScript?
KSS
12
Angular 2
Глава №2 - Горы отвращения
13
Angular 2 is Beta*
14
* - now RC1
ASP.Net MVC - Developer Preview 2
15
16
17
([]) [] ()
([]) [] ()
([]) []
([]) [] ()
([]
([]) []
([]) [] ()
([])
18
19
/**
* Simplest possible template in AngularJs-ISH style
*
* @param {String} template - template string
* @param {Object} ctx - template context
* @param {Object} eventHandlerObject - object that will be used as "this" in event handling
* @returns {Node} returns dom node element
*/
export default function angularish(template, ctx, eventHandlerObject) {
var node;
var container = document.createElement('div');
container.innerHTML = template;
var walker = document.createTreeWalker(container, NodeFilter.SHOW_ELEMENT, null, false);
while (node = walker.nextNode()) {
// inheritance of context
node.ctx = node.ctx || node.parentNode.ctx || ctx;
// ng-scope allows you to change scope of the node (new scope can be any property of old
scope)
if (node.getAttribute('ng-scope')) {
node.ctx = _getValue(node.ctx, node.getAttribute('ng-scope'));
}
// ng-loop will repeat first child (TODO: reapeat content) and assign correct context
if (node.getAttribute('ng-loop')) {
20
/**
* Simplest possible template in AngularJs-ISH style
*
* @param {String} template - template string
* @param {Object} ctx - template context
* @param {Object} eventHandlerObject - object that will be used as "this" in event handling
* @returns {Node} returns dom node element
*/
export default function angularish(template, ctx, eventHandlerObject) {
var node;
var container = document.createElement('div');
container.innerHTML = template;
var walker = document.createTreeWalker(container, NodeFilter.SHOW_ELEMENT, null, false);
while (node = walker.nextNode()) {
// inheritance of context
node.ctx = node.ctx || node.parentNode.ctx || ctx;
// ng-scope allows you to change scope of the node (new scope can be any property of old
scope)
if (node.getAttribute('ng-scope')) {
node.ctx = _getValue(node.ctx, node.getAttribute('ng-scope'));
}
// ng-loop will repeat first child (TODO: reapeat content) and assign correct context
if (node.getAttribute('ng-loop')) {
21
/**
* Simplest possible template in AngularJs-ISH style
*
* @param {String} template - template string
* @param {Object} ctx - template context
* @param {Object} eventHandlerObject - object that will be used as "this" in event handling
* @returns {Node} returns dom node element
*/
export default function angularish(template, ctx, eventHandlerObject) {
var node;
var container = document.createElement('div');
container.innerHTML = template;
var walker = document.createTreeWalker(container, NodeFilter.SHOW_ELEMENT, null, false);
while (node = walker.nextNode()) {
// inheritance of context
node.ctx = node.ctx || node.parentNode.ctx || ctx;
// ng-scope allows you to change scope of the node (new scope can be any property of old
scope)
if (node.getAttribute('ng-scope')) {
node.ctx = _getValue(node.ctx, node.getAttribute('ng-scope'));
}
// ng-loop will repeat first child (TODO: reapeat content) and assign correct context
if (node.getAttribute('ng-loop')) {
22
node.value = _getValue(node.ctx, node.getAttribute('ng-value'));
}
// ng-selected will set selected attribute depending on true-finess of value
if (node.getAttribute('ng-selected')) {
var selected = _getValue(node.ctx, node.getAttribute('ng-selected'));
if (selected) {
node.setAttribute('selected', 'yes');
}
}
// ng-text will assign text to node no need for escaping
if (node.getAttribute('ng-text')) {
node.innerText = _getValue(node.ctx, node.getAttribute('ng-text'));
}
// ng-class will simply assign class from defined property
if (node.getAttribute('ng-class')) {
var classVal = _getValue(node.ctx, node.getAttribute('ng-class'));
if (classVal) {
node.className += ' ' + classVal;
}
}
// ng-show shows elements depending on true-finess of the value
if (node.getAttribute('ng-show')) {
23
// ng-scope allows you to change scope of the node (new scope can be any property of old
scope)
if (node.getAttribute('ng-scope')) {
node.ctx = _getValue(node.ctx, node.getAttribute('ng-scope'));
}
// ng-loop will repeat first child (TODO: reapeat content) and assign correct context
if (node.getAttribute('ng-loop')) {
var child = node.children[0];
var array = _getValue(node.ctx, node.getAttribute('ng-loop')) || [];
node.removeChild(child);
array.forEach((item) => {
child = child.cloneNode(true);
child.ctx = item;
node.appendChild(child);
});
}
// ng-value will assign value to node
if (node.getAttribute('ng-value')) {
node.value = _getValue(node.ctx, node.getAttribute('ng-value'));
}
// ng-selected will set selected attribute depending on true-finess of value
if (node.getAttribute('ng-selected')) {
24
// ng-change will add "change" event handler
if (node.getAttribute('ng-change')) {
// closure to rescue
((node)=> {
node.addEventListener('change', (event) => {
eventHandlerObject[node.getAttribute(‘ng-change')]
.bind(eventHandlerObject)(node.ctx, event);
}, true);
})(node);
}
// ng-click will add "click" event handler
if (node.getAttribute('ng-click')) {
// closure to rescue
((node)=> {
node.addEventListener('click', (event) => {
eventHandlerObject[node.getAttribute(‘ng-click')]
.bind(eventHandlerObject)(node.ctx, event);
}, true);
})(node);
}
}
return container;
}
function _getValue(ctx, attrVal) {
if (attrVal === 'self') {
return ctx;
}
25
}
// ng-hide shows elements depending on false-iness of the value
if (node.getAttribute('ng-hide')) {
var isHidden = _getValue(node.ctx, node.getAttribute('ng-hide'));
if (isHidden) {
node.style.display = 'none';
}
}
// ng-change will add "change" event handler
if (node.getAttribute('ng-change')) {
// closure to rescue
((node)=> {
node.addEventListener('change', (event) => {
eventHandlerObject[node.getAttribute(‘ng-change')]
.bind(eventHandlerObject)(node.ctx, event);
}, true);
})(node);
}
// ng-click will add "click" event handler
if (node.getAttribute('ng-click')) {
// closure to rescue
((node)=> {
node.addEventListener('click', (event) => {
eventHandlerObject[node.getAttribute(‘ng-click')]
.bind(eventHandlerObject)(node.ctx, event);
}, true);
})(node);
}
26
[]
()
[()]
27
[property]=‘value’ -> property=‘value’
()
[()]
28
[property]=‘value’ -> property=‘value’
(event)=‘handler()’ -> on-event=‘handler()’
[()]
29
[property]=‘value’ -> property=‘value’
(event)=‘handler()’ -> on-event=‘handler()’
[(target)]=‘value’ -> on-change=‘update()’
-> target=‘value’
30
bind-property=‘value’ -> property=‘value’
(event)=‘handler()’ -> on-event=‘handler()’
[(target)]=‘value’ -> on-change=‘update()’
-> target=‘value’
31
bind-property=‘value’ -> property=‘value’
on-event=‘handler()’ -> on-event=‘handler()’
[(target)]=‘value’ -> on-change=‘update()’
-> target=‘value’
32
bind-property=‘value’ -> property=‘value’
on-event=‘handler()’ -> on-event=‘handler()’
bindon-prop=‘value’ -> on-change=‘update()’
-> target=‘value’
33
<hero-detail *ngIf="currentHero"
[hero]="currentHero"/>
34
<hero-detail template="ngIf:currentHero"
[hero]="currentHero"/>
35
<template [ngIf]="currentHero">
<hero-detail [hero]="currentHero"></hero-detail>
</template>
System.js & JSPM & System.js Builder
36
http://plnkr.co/
System.js & JSPM & System.js Builder
37
<title>angular2 playground</title>
<link rel="stylesheet" href="style.css" />
<script src="https://code.angularjs.org/2.0.0-beta.17/
angular2-polyfills.js"></script>
<script src="https://code.angularjs.org/tools/system.js"></
script>
<script src="https://code.angularjs.org/tools/
typescript.js"></script>
<script src="config.js"></script>
<script>
System.import('app')
.catch(console.error.bind(console));
</script>
</head>
System.js & JSPM & System.js Builder
38
<title>angular2 playground</title>
<link rel="stylesheet" href="style.css" />
<script src="https://code.angularjs.org/2.0.0-beta.17/
angular2-polyfills.js"></script>
<script src="https://code.angularjs.org/tools/system.js"></
script>
<script src="https://code.angularjs.org/tools/
typescript.js"></script>
<script src="config.js"></script>
<script>
System.import('app')
.catch(console.error.bind(console));
</script>
</head>
39
System.config({
//use typescript for compilation
transpiler: 'typescript',
//typescript compiler options
typescriptOptions: {
emitDecoratorMetadata: true
},
//map tells the System loader where to look for things
map: {
app: "./src",
'@angular': 'https://npmcdn.com/@angular',
'rxjs': 'https://npmcdn.com/rxjs@5.0.0-beta.6'
},
//packages defines our app package
packages: {
app: {
main: './main.ts',
defaultExtension: 'ts'
},
'@angular/core': {
main: 'core.umd.js',
defaultExtension: 'js'
},
'@angular/compiler': {
main: 'compiler.umd.js',
defaultExtension: 'js'
},
'@angular/common': {
main: 'common.umd.js',
defaultExtension: 'js'
},
'@angular/platform-browser-dynamic': {
main: 'platform-browser-dynamic.umd.js',
defaultExtension: 'js'
},
'@angular/platform-browser': {
main: 'platform-browser.umd.js',
defaultExtension: 'js'
},
rxjs: {
defaultExtension: 'js'
}
}
});
40
System.config({
//use typescript for compilation
transpiler: 'typescript',
//typescript compiler options
typescriptOptions: {
emitDecoratorMetadata: true
},
//map tells the System loader where to look for things
map: {
app: "./src",
'@angular': 'https://npmcdn.com/@angular',
'rxjs': 'https://npmcdn.com/rxjs@5.0.0-beta.6'
},
//packages defines our app package
packages: {
app: {
main: './main.ts',
defaultExtension: 'ts'
},
'@angular/core': {
main: 'core.umd.js',
defaultExtension: 'js'
},
'@angular/compiler': {
main: 'compiler.umd.js',
defaultExtension: 'js'
},
'@angular/common': {
main: 'common.umd.js',
defaultExtension: 'js'
},
'@angular/platform-browser-dynamic': {
main: 'platform-browser-dynamic.umd.js',
defaultExtension: 'js'
},
'@angular/platform-browser': {
main: 'platform-browser.umd.js',
defaultExtension: 'js'
},
rxjs: {
defaultExtension: 'js'
}
}
});
44 строчки конфига
Не хуже чем Webpack
• Официальный Angular QuickStart репозиторий
• Angular CLI
• Yoman / Slush - генераторы
TypeScript
42
TypeScript
43
TypeScript
44
TypeScript
45
• .Net, Java, Scala background
• SOLID, Design Patterns
• 1.8.10
• Poor documentation - «google search ftw»
Глава №3 - Добыча
46
Размер
47
Development
Production
Size in KB
0 50 100 150 200 250 300 350 400
React Angular 1 Angular 2
Размер - Angular 2 Router
48
Размер - Angular 2 Router
49
Размер - Angular 2 Router
50
CSS
51
import {Component} from '@angular/core'
@Component({
selector: 'my-app',
providers: [],
styles: [`
h2 { color: red; }
`],
template: `
<div>
<h2>Hello {{name}}</h2>
</div>
`,
directives: []
})
export class App {
constructor() {
this.name = 'Angular2 (Release Candidate!)'
}
}
CSS
52
import {Component} from '@angular/core'
@Component({
selector: 'my-app',
providers: [],
styles: [`
body { color: red; }
`],
template: `
<div>
<h2>Hello {{name}}</h2>
</div>
`,
directives: []
})
export class App {
constructor() {
this.name = 'Angular2 (Release Candidate!)'
}
}
CSS
53
Speed - templates
54
55
import { Component } from '@angular/core';
@Component({
moduleId: module.id,
selector: 'project-name-app',
template: `
<h1>
{{title}}
</h1>
`,
styleUrls: ['project-name.component.css']
})
export class PROJECTNAMEAppComponent {
title = 'project-name works!';
}
56
new jit_StaticNodeDebugInfo0([],null,{}),
new jit_StaticNodeDebugInfo0([],null,{}),
new jit_StaticNodeDebugInfo0([],null,{})
]
;
var renderType_PROJECTNAMEAppComponent = null;
function _View_PROJECTNAMEAppComponent0(viewUtils,parentInjector,declarationEl) {
var self = this;
jit_DebugAppView1.call(this,
_View_PROJECTNAMEAppComponent0,renderType_PROJECTNAMEAppComponent,jit_ViewType_COMPONENT2,viewUtils,parentInjec
rationEl,jit_ChangeDetectionStrategy_CheckAlways3,nodeDebugInfos_PROJECTNAMEAppComponent0);
}
_View_PROJECTNAMEAppComponent0.prototype = Object.create(jit_DebugAppView1.prototype);
_View_PROJECTNAMEAppComponent0.prototype.createInternal = function(rootSelector) {
var self = this;
var parentRenderNode = self.renderer.createViewRoot(self.declarationAppElement.nativeElement);
self._el_0 = self.renderer.createElement(parentRenderNode,'h1',self.debug(0,0,0));
self._text_1 = self.renderer.createText(self._el_0,'',self.debug(1,0,4));
self._text_2 = self.renderer.createText(parentRenderNode,'n',self.debug(2,2,5));
self._expr_0 = jit_uninitialized4;
self.init([],[
self._el_0,
self._text_1,
self._text_2
]
,[],[]);
return null;
};
_View_PROJECTNAMEAppComponent0.prototype.detectChangesInternal = function(throwOnChange) {
var self = this;
self.detectContentChildrenChanges(throwOnChange);
self.debug(1,0,4);
57
new jit_StaticNodeDebugInfo0([],null,{}),
new jit_StaticNodeDebugInfo0([],null,{}),
new jit_StaticNodeDebugInfo0([],null,{})
]
;
var renderType_PROJECTNAMEAppComponent = null;
function _View_PROJECTNAMEAppComponent0(viewUtils,parentInjector,declarationEl) {
var self = this;
jit_DebugAppView1.call(this,
_View_PROJECTNAMEAppComponent0,renderType_PROJECTNAMEAppComponent,jit_ViewType_COMPONENT2,viewUtils,parentInjec
rationEl,jit_ChangeDetectionStrategy_CheckAlways3,nodeDebugInfos_PROJECTNAMEAppComponent0);
}
_View_PROJECTNAMEAppComponent0.prototype = Object.create(jit_DebugAppView1.prototype);
_View_PROJECTNAMEAppComponent0.prototype.createInternal = function(rootSelector) {
var self = this;
var parentRenderNode = self.renderer.createViewRoot(self.declarationAppElement.nativeElement);
self._el_0 = self.renderer.createElement(parentRenderNode,'h1',self.debug(0,0,0));
self._text_1 = self.renderer.createText(self._el_0,'',self.debug(1,0,4));
self._text_2 = self.renderer.createText(parentRenderNode,'n',self.debug(2,2,5));
self._expr_0 = jit_uninitialized4;
self.init([],[
self._el_0,
self._text_1,
self._text_2
]
,[],[]);
return null;
};
_View_PROJECTNAMEAppComponent0.prototype.detectChangesInternal = function(throwOnChange) {
var self = this;
self.detectContentChildrenChanges(throwOnChange);
self.debug(1,0,4);
58
self.renderer.createElement
self.renderer.createText
59
Как построить DOM
Роман Дворнов
Speed
immutability
60
import { Component, Pipe, PipeTransform } from '@angular/core';
@Pipe({ name: 'isOdd' })
export class IsOddPipe implements PipeTransform {
transform(array:any[]) { return array.filter(item => item.isOdd); }
}
@Component({
moduleId: module.id,
selector: 'project-name-app',
pipes: [IsOddPipe],
template: `
<button (click)="add()">add</button>
<div>
<div *ngFor="let item of list | isOdd">
{{ item.name }}
</div>
</div>
`,
styleUrls: ['project-name.component.css']
})
export class PROJECTNAMEAppComponent {
list = []
add() {
this.list.push({ name: ‘test', isOdd: !!(this.list.length % 2)
})
}
}
Speed
immutability
61
import { Component, Pipe, PipeTransform } from '@angular/core';
@Pipe({ name: 'isOdd' })
export class IsOddPipe implements PipeTransform {
transform(array:any[]) { return array.filter(item => item.isOdd); }
}
@Component({
moduleId: module.id,
selector: 'project-name-app',
pipes: [IsOddPipe],
template: `
<button (click)="add()">add</button>
<div>
<div *ngFor="let item of list | isOdd">
{{ item.name }}
</div>
</div>
`,
styleUrls: ['project-name.component.css']
})
export class PROJECTNAMEAppComponent {
list = []
add() {
this.list.push({ name: ‘test', isOdd: !!(this.list.length % 2)
})
}
}
Speed
immutability
62
import { Component, Pipe, PipeTransform } from '@angular/core';
@Pipe({ name: 'isOdd' })
export class IsOddPipe implements PipeTransform {
transform(array:any[]) { return array.filter(item => item.isOdd); }
}
@Component({
moduleId: module.id,
selector: 'project-name-app',
pipes: [IsOddPipe],
template: `
<button (click)="add()">add</button>
<div>
<div *ngFor="let item of list | isOdd">
{{ item.name }}
</div>
</div>
`,
styleUrls: ['project-name.component.css']
})
export class PROJECTNAMEAppComponent {
list = []
add() {
this.list.push({ name: ‘test', isOdd: !!(this.list.length % 2)
})
}
}
Speed
immutability
63
import { Component, Pipe, PipeTransform } from '@angular/core';
@Pipe({ name: ‘isOdd’, is_pure: false })
export class IsOddPipe implements PipeTransform {
transform(array:any[]) { return array.filter(item => item.isOdd); }
}
@Component({
moduleId: module.id,
selector: 'project-name-app',
pipes: [IsOddPipe],
template: `
<button (click)="add()">add</button>
<div>
<div *ngFor="let item of list | isOdd">
{{ item.name }}
</div>
</div>
`,
styleUrls: ['project-name.component.css']
})
export class PROJECTNAMEAppComponent {
list = []
add() {
this.list.push({ name: ‘test', isOdd: !!(this.list.length % 2)
})
}
}
Speed
immutability
64
import { Component, Pipe, PipeTransform } from '@angular/core';
@Pipe({ name: 'isOdd' })
export class IsOddPipe implements PipeTransform {
transform(array:any[]) { return array.filter(item => item.isOdd); }
}
@Component({
moduleId: module.id,
selector: 'project-name-app',
pipes: [IsOddPipe],
template: `
<button (click)="add()">add</button>
<div>
<div *ngFor="let item of list | isOdd">
{{ item.name }}
</div>
</div>
`,
styleUrls: ['project-name.component.css']
})
export class PROJECTNAMEAppComponent {
list = []
add() {
this.list = this.list.splice().filter((i) => i % 2)
})
}
}
Speed - zone.js
65
Zone.fork().run(function () {
zone.inTheZone = true;
setTimeout(function () {
console.log('in the zone: ' + !!zone.inTheZone);
}, 0);
});
console.log('in the zone: ' + !!zone.inTheZone);
—————————————————————————————
'in the zone: false'
'in the zone: true'
Speed - zone.js
66
Zone.fork().run(function () {
zone.inTheZone = true;
setTimeout(function () {
console.log('in the zone: ' + !!zone.inTheZone);
}, 0);
});
console.log('in the zone: ' + !!zone.inTheZone);
—————————————————————————————
'in the zone: false'
'in the zone: true'
TypeScript OOP
67
class GenericService<T> {
items: Array<T> = []
addItem(item: T) {
this.items.push(item)
}
}
interface User {
id: number,
name: string
}
interface Creatives {
type: string,
value: string
}
TypeScript OOP
68
var s = new GenericService<User>();
s.addItem({
id: 1, name: 'asda'
});
s.addItem({
type: ‘asda' // will fail
})
Глава №4 - Первые потери
69
… а вот этого я не ожидал
Потеря почти всей кодовой базы
70
Promise -> RXJS
71
Promise -> RXJS
72
ЗДЕСЬ БЫЛ PROMISE
Promise -> RXJS
73
import {Http, HTTP_PROVIDERS} from 'angular2/http';
@Component({
selector: 'http-app',
viewProviders: [HTTP_PROVIDERS],
templateUrl: 'people.html'
})
class PeopleComponent {
constructor(http: Http) {
http.get('people.json')
.map(res => res.json())
.subscribe(people => this.people = people);
}
}
Promise -> RXJS
74
import {Http, HTTP_PROVIDERS} from 'angular2/http';
@Component({
selector: 'http-app',
viewProviders: [HTTP_PROVIDERS],
templateUrl: 'people.html'
})
class PeopleComponent {
constructor(http: Http) {
http.get('people.json')
.map(res => res.json())
.subscribe(people => this.people = people);
}
}
Promise -> RXJS
75
import {Http, HTTP_PROVIDERS} from 'angular2/http';
@Component({
selector: 'http-app',
viewProviders: [HTTP_PROVIDERS],
templateUrl: 'people.html'
})
class PeopleComponent {
constructor(http: Http) {
http.get('people.json')
.map(res => res.json())
.subscribe(people => this.people = people);
}
}
RXJS
76
RXJS
77
interface IObservable<T>
{
IDisposable Subscribe(IObserver observer);
}
interface IObserver<T>
{
void OnCompleted();
void OnNext(T value);
void OnError(Exception e);
}
ngResources
78
var User = $resource('/user/:userId', {userId:'@id'});
User.get({userId:123}, function(user) {
user.abc = true;
user.$save();
});
ngResources
79
var User = $resource('/user/:userId', {userId:'@id'});
User.get({userId:123}, function(user) {
user.abc = true;
user.$save();
});
Встроенные паттерны канули в небытие!
80
1) component
2) directive
3) filter
4) service
5) provider
6) constant
7) config
8) run
9) module
Встроенные паттерны канули в небытие!
81
1) component
2) template
3) directive
4) route
5) pipe
6) service *
Формы
82
1) [(ngModel)]
Формы
83
1) [(ngModel)]
2) ng-valid | ng-invalid | ng-dirty | ng-pristine | ng-touched | ng-untouched
Формы
84
1) [(ngModel)]
2) ng-valid | ng-invalid | ng-dirty | ng-pristine | ng-touched | ng-untouched
3) FormModel + FormBuilder
Формы
85
1) [(ngModel)]
2) ng-valid | ng-invalid | ng-dirty | ng-pristine | ng-touched | ng-untouched
3) FormModel + FormBuilder
4) Валидация не стала легче
Глава №5 - Happy End
86
Мы уже переехали на Angular 2?
87
НЕТ
88
Почему?
89
1) Потому что Angular 1 не так уж и плох, а если задуматься …
Почему?
90
1) Потому что Angular 1 не так уж и плох, а если задуматься …
2) Потому что React 15 не так уж и плох, а если задуматься …
Почему?
91
1) Потому что Angular 1 не так уж и плох, а если задуматься …
2) Потому что React 15 не так уж и плох, а если задуматься …
3) Потому что Ember не так уж и плох, а если задуматься …
Почему?
92
1) Кодовая база
2) Уровень вхождения
3) Незаконченность*
Почему?
93
1) Кодовая база
2) Уровень вхождения
3) Незаконченность*
Есть ли надежда?
94
Наши шаги
95
1) TypeScript OOP - e2e tests
2) Angular 1.4.x -> 1.5.x
3) AutoNgConverter
О чем мы не поговорили?
96
97
Progressive Web Apps
Native
- Ionic Framework,
- NativeScript
- React Native.
Desktop
- Electron
Universal
- node.js,
- .NET,
- PHP
Dependency Injection
Angular CLI
IDEs
Testing
- patched Karma, Protractor
Animation
Accessibility
Developer Tools
98
-Redux ( ngrx / ng2-redux )
-FLUX
-MV* ( MVC, MVP, MVVM )
-MALEVICH ( COD.js )
Приятного
аппетита!
Tweeter: #Ai_boy
Gitter: aiboy
99
http://bit.ly/1XP0dEh

More Related Content

What's hot

JavascriptMVC
JavascriptMVCJavascriptMVC
JavascriptMVC4lb0
 
Java script.trend(spec)
Java script.trend(spec)Java script.trend(spec)
Java script.trend(spec)dynamis
 
SSP - The Simple Singleton Pattern
SSP - The Simple Singleton PatternSSP - The Simple Singleton Pattern
SSP - The Simple Singleton PatternRodolfo Dias
 
HTTP Interceptors com AngularJS
HTTP Interceptors com AngularJSHTTP Interceptors com AngularJS
HTTP Interceptors com AngularJSRodrigo Branas
 
Android Fast Track CRUD Android PHP MySql
Android Fast Track CRUD Android PHP MySqlAndroid Fast Track CRUD Android PHP MySql
Android Fast Track CRUD Android PHP MySqlAgus Haryanto
 
Aller plus loin avec Doctrine2
Aller plus loin avec Doctrine2Aller plus loin avec Doctrine2
Aller plus loin avec Doctrine2André Tapia
 
Practical JavaScript Programming - Session 2/8
Practical JavaScript Programming - Session 2/8Practical JavaScript Programming - Session 2/8
Practical JavaScript Programming - Session 2/8Wilson Su
 
ECMAScript 6 im Produktivbetrieb
ECMAScript 6 im ProduktivbetriebECMAScript 6 im Produktivbetrieb
ECMAScript 6 im ProduktivbetriebSebastian Springer
 
JAVA Program in NetBeans
JAVA Program in NetBeansJAVA Program in NetBeans
JAVA Program in NetBeansHimanshiSingh71
 
Android Bootcamp Santa Fe GTUG
Android Bootcamp Santa Fe GTUGAndroid Bootcamp Santa Fe GTUG
Android Bootcamp Santa Fe GTUGmatiasmolinas
 
Unit Testing con Jest + Enzime para ReactJs
Unit Testing con Jest + Enzime para ReactJsUnit Testing con Jest + Enzime para ReactJs
Unit Testing con Jest + Enzime para ReactJsGabrielComas2
 
Юнит тестирование в Zend Framework 2.0
Юнит тестирование в Zend Framework 2.0Юнит тестирование в Zend Framework 2.0
Юнит тестирование в Zend Framework 2.0zfconfua
 
Twig, los mejores trucos y técnicas avanzadas
Twig, los mejores trucos y técnicas avanzadasTwig, los mejores trucos y técnicas avanzadas
Twig, los mejores trucos y técnicas avanzadasJavier Eguiluz
 
C# Starter L01-Intro and Warm-up
C# Starter L01-Intro and Warm-upC# Starter L01-Intro and Warm-up
C# Starter L01-Intro and Warm-upMohammad Shaker
 

What's hot (20)

Proxy & CGLIB
Proxy & CGLIBProxy & CGLIB
Proxy & CGLIB
 
JavascriptMVC
JavascriptMVCJavascriptMVC
JavascriptMVC
 
Java script.trend(spec)
Java script.trend(spec)Java script.trend(spec)
Java script.trend(spec)
 
SSP - The Simple Singleton Pattern
SSP - The Simple Singleton PatternSSP - The Simple Singleton Pattern
SSP - The Simple Singleton Pattern
 
HTTP Interceptors com AngularJS
HTTP Interceptors com AngularJSHTTP Interceptors com AngularJS
HTTP Interceptors com AngularJS
 
Android Fast Track CRUD Android PHP MySql
Android Fast Track CRUD Android PHP MySqlAndroid Fast Track CRUD Android PHP MySql
Android Fast Track CRUD Android PHP MySql
 
Aller plus loin avec Doctrine2
Aller plus loin avec Doctrine2Aller plus loin avec Doctrine2
Aller plus loin avec Doctrine2
 
Testování prakticky
Testování praktickyTestování prakticky
Testování prakticky
 
JSF 2 and Ajax
JSF 2 and  AjaxJSF 2 and  Ajax
JSF 2 and Ajax
 
Practical JavaScript Programming - Session 2/8
Practical JavaScript Programming - Session 2/8Practical JavaScript Programming - Session 2/8
Practical JavaScript Programming - Session 2/8
 
JQuery
JQueryJQuery
JQuery
 
ECMAScript 6 im Produktivbetrieb
ECMAScript 6 im ProduktivbetriebECMAScript 6 im Produktivbetrieb
ECMAScript 6 im Produktivbetrieb
 
JAVA Program in NetBeans
JAVA Program in NetBeansJAVA Program in NetBeans
JAVA Program in NetBeans
 
Android Bootcamp Santa Fe GTUG
Android Bootcamp Santa Fe GTUGAndroid Bootcamp Santa Fe GTUG
Android Bootcamp Santa Fe GTUG
 
Unit Testing con Jest + Enzime para ReactJs
Unit Testing con Jest + Enzime para ReactJsUnit Testing con Jest + Enzime para ReactJs
Unit Testing con Jest + Enzime para ReactJs
 
Юнит тестирование в Zend Framework 2.0
Юнит тестирование в Zend Framework 2.0Юнит тестирование в Zend Framework 2.0
Юнит тестирование в Zend Framework 2.0
 
Twig, los mejores trucos y técnicas avanzadas
Twig, los mejores trucos y técnicas avanzadasTwig, los mejores trucos y técnicas avanzadas
Twig, los mejores trucos y técnicas avanzadas
 
1- Sourcecode Array
1- Sourcecode Array1- Sourcecode Array
1- Sourcecode Array
 
Einführung in Meteor
Einführung in MeteorEinführung in Meteor
Einführung in Meteor
 
C# Starter L01-Intro and Warm-up
C# Starter L01-Intro and Warm-upC# Starter L01-Intro and Warm-up
C# Starter L01-Intro and Warm-up
 

Viewers also liked

Конструктор / Денис Паясь (Яндекс)
Конструктор / Денис Паясь (Яндекс)Конструктор / Денис Паясь (Яндекс)
Конструктор / Денис Паясь (Яндекс)Ontico
 
Vue.js и его брат-близнец Vue-server.js / Андрей Солодовников (НГС)
Vue.js и его брат-близнец Vue-server.js / Андрей Солодовников (НГС)Vue.js и его брат-близнец Vue-server.js / Андрей Солодовников (НГС)
Vue.js и его брат-близнец Vue-server.js / Андрей Солодовников (НГС)Ontico
 
React новая эра фронтенд разработки / Роберт Харитонов (Liberty Global)
React новая эра фронтенд разработки / Роберт Харитонов (Liberty Global)React новая эра фронтенд разработки / Роберт Харитонов (Liberty Global)
React новая эра фронтенд разработки / Роберт Харитонов (Liberty Global)Ontico
 
Amazing threesome, rrr... React. Redux. Real world / Ростислав Галкин (Babo)
Amazing threesome, rrr... React. Redux. Real world / Ростислав Галкин (Babo)Amazing threesome, rrr... React. Redux. Real world / Ростислав Галкин (Babo)
Amazing threesome, rrr... React. Redux. Real world / Ростислав Галкин (Babo)Ontico
 
"Angular 2: Всех переиграл" Евгений Жарков
"Angular 2: Всех переиграл" Евгений Жарков"Angular 2: Всех переиграл" Евгений Жарков
"Angular 2: Всех переиграл" Евгений ЖарковFwdays
 
FrontDays #3. Иван Федяев, Эволюция JavaScript. Обзор нововведений ECMAScript 6
FrontDays #3. Иван Федяев, Эволюция JavaScript. Обзор нововведений ECMAScript 6FrontDays #3. Иван Федяев, Эволюция JavaScript. Обзор нововведений ECMAScript 6
FrontDays #3. Иван Федяев, Эволюция JavaScript. Обзор нововведений ECMAScript 6FrontDays
 
Пользовательские свойства как основа архитектуры CSS / Павел Ловцевич (LOVATA)
Пользовательские свойства как основа архитектуры CSS / Павел Ловцевич (LOVATA)Пользовательские свойства как основа архитектуры CSS / Павел Ловцевич (LOVATA)
Пользовательские свойства как основа архитектуры CSS / Павел Ловцевич (LOVATA)Ontico
 
Что делать, когда костыли уже не помогают. Опыт tutu.ru / Роман Грунтович (tu...
Что делать, когда костыли уже не помогают. Опыт tutu.ru / Роман Грунтович (tu...Что делать, когда костыли уже не помогают. Опыт tutu.ru / Роман Грунтович (tu...
Что делать, когда костыли уже не помогают. Опыт tutu.ru / Роман Грунтович (tu...Ontico
 
Превышаем скоростные лимиты с Angular 2 / Алексей Охрименко (IPONWEB)
Превышаем скоростные лимиты с Angular 2 / Алексей Охрименко (IPONWEB)Превышаем скоростные лимиты с Angular 2 / Алексей Охрименко (IPONWEB)
Превышаем скоростные лимиты с Angular 2 / Алексей Охрименко (IPONWEB)Ontico
 
UX-дизайнер, ты ли это. Навыки проектировщика в стилизации интерфейсов / Илья...
UX-дизайнер, ты ли это. Навыки проектировщика в стилизации интерфейсов / Илья...UX-дизайнер, ты ли это. Навыки проектировщика в стилизации интерфейсов / Илья...
UX-дизайнер, ты ли это. Навыки проектировщика в стилизации интерфейсов / Илья...Ontico
 
Как мы разрабатываем новый фронтенд / Филипп Нехаев (Tinkoff.ru)
Как мы разрабатываем новый фронтенд / Филипп Нехаев (Tinkoff.ru)Как мы разрабатываем новый фронтенд / Филипп Нехаев (Tinkoff.ru)
Как мы разрабатываем новый фронтенд / Филипп Нехаев (Tinkoff.ru)Ontico
 
Стабильность WebGL приложений / Кирилл Дмитренко (Яндекс)
Стабильность WebGL приложений / Кирилл Дмитренко (Яндекс)Стабильность WebGL приложений / Кирилл Дмитренко (Яндекс)
Стабильность WebGL приложений / Кирилл Дмитренко (Яндекс)Ontico
 
Классические архитектуры во фронтенде / Александра Шинкевич (LOVATA)
Классические архитектуры во фронтенде / Александра Шинкевич (LOVATA)Классические архитектуры во фронтенде / Александра Шинкевич (LOVATA)
Классические архитектуры во фронтенде / Александра Шинкевич (LOVATA)Ontico
 
Angular vs Angular 2 vs React. Сергей Александров
Angular vs Angular 2 vs React. Сергей АлександровAngular vs Angular 2 vs React. Сергей Александров
Angular vs Angular 2 vs React. Сергей АлександровEatDog
 
Радости и гадости регрессионного тестирования вёрстки / Алексей Малейков (HTM...
Радости и гадости регрессионного тестирования вёрстки / Алексей Малейков (HTM...Радости и гадости регрессионного тестирования вёрстки / Алексей Малейков (HTM...
Радости и гадости регрессионного тестирования вёрстки / Алексей Малейков (HTM...Ontico
 
Архитектура поиска в Avito / Андрей Смирнов (Avito)
Архитектура поиска в Avito / Андрей Смирнов (Avito)Архитектура поиска в Avito / Андрей Смирнов (Avito)
Архитектура поиска в Avito / Андрей Смирнов (Avito)Ontico
 
Использование Tarantool в качестве платформы виртуализации данных / Константи...
Использование Tarantool в качестве платформы виртуализации данных / Константи...Использование Tarantool в качестве платформы виртуализации данных / Константи...
Использование Tarantool в качестве платформы виртуализации данных / Константи...Ontico
 
Чему мы научились, разрабатывая микросервисы / Вадим Мадисон (RuTube)
Чему мы научились, разрабатывая микросервисы / Вадим Мадисон (RuTube)Чему мы научились, разрабатывая микросервисы / Вадим Мадисон (RuTube)
Чему мы научились, разрабатывая микросервисы / Вадим Мадисон (RuTube)Ontico
 
FrontDays #1. Алексей Ульянов, React.js и методологии разработки на нём
FrontDays #1. Алексей Ульянов, React.js и методологии разработки на нёмFrontDays #1. Алексей Ульянов, React.js и методологии разработки на нём
FrontDays #1. Алексей Ульянов, React.js и методологии разработки на нёмFrontDays
 

Viewers also liked (20)

Конструктор / Денис Паясь (Яндекс)
Конструктор / Денис Паясь (Яндекс)Конструктор / Денис Паясь (Яндекс)
Конструктор / Денис Паясь (Яндекс)
 
Vue.js и его брат-близнец Vue-server.js / Андрей Солодовников (НГС)
Vue.js и его брат-близнец Vue-server.js / Андрей Солодовников (НГС)Vue.js и его брат-близнец Vue-server.js / Андрей Солодовников (НГС)
Vue.js и его брат-близнец Vue-server.js / Андрей Солодовников (НГС)
 
React новая эра фронтенд разработки / Роберт Харитонов (Liberty Global)
React новая эра фронтенд разработки / Роберт Харитонов (Liberty Global)React новая эра фронтенд разработки / Роберт Харитонов (Liberty Global)
React новая эра фронтенд разработки / Роберт Харитонов (Liberty Global)
 
Amazing threesome, rrr... React. Redux. Real world / Ростислав Галкин (Babo)
Amazing threesome, rrr... React. Redux. Real world / Ростислав Галкин (Babo)Amazing threesome, rrr... React. Redux. Real world / Ростислав Галкин (Babo)
Amazing threesome, rrr... React. Redux. Real world / Ростислав Галкин (Babo)
 
"Angular 2: Всех переиграл" Евгений Жарков
"Angular 2: Всех переиграл" Евгений Жарков"Angular 2: Всех переиграл" Евгений Жарков
"Angular 2: Всех переиграл" Евгений Жарков
 
FrontDays #3. Иван Федяев, Эволюция JavaScript. Обзор нововведений ECMAScript 6
FrontDays #3. Иван Федяев, Эволюция JavaScript. Обзор нововведений ECMAScript 6FrontDays #3. Иван Федяев, Эволюция JavaScript. Обзор нововведений ECMAScript 6
FrontDays #3. Иван Федяев, Эволюция JavaScript. Обзор нововведений ECMAScript 6
 
Angular2
Angular2Angular2
Angular2
 
Пользовательские свойства как основа архитектуры CSS / Павел Ловцевич (LOVATA)
Пользовательские свойства как основа архитектуры CSS / Павел Ловцевич (LOVATA)Пользовательские свойства как основа архитектуры CSS / Павел Ловцевич (LOVATA)
Пользовательские свойства как основа архитектуры CSS / Павел Ловцевич (LOVATA)
 
Что делать, когда костыли уже не помогают. Опыт tutu.ru / Роман Грунтович (tu...
Что делать, когда костыли уже не помогают. Опыт tutu.ru / Роман Грунтович (tu...Что делать, когда костыли уже не помогают. Опыт tutu.ru / Роман Грунтович (tu...
Что делать, когда костыли уже не помогают. Опыт tutu.ru / Роман Грунтович (tu...
 
Превышаем скоростные лимиты с Angular 2 / Алексей Охрименко (IPONWEB)
Превышаем скоростные лимиты с Angular 2 / Алексей Охрименко (IPONWEB)Превышаем скоростные лимиты с Angular 2 / Алексей Охрименко (IPONWEB)
Превышаем скоростные лимиты с Angular 2 / Алексей Охрименко (IPONWEB)
 
UX-дизайнер, ты ли это. Навыки проектировщика в стилизации интерфейсов / Илья...
UX-дизайнер, ты ли это. Навыки проектировщика в стилизации интерфейсов / Илья...UX-дизайнер, ты ли это. Навыки проектировщика в стилизации интерфейсов / Илья...
UX-дизайнер, ты ли это. Навыки проектировщика в стилизации интерфейсов / Илья...
 
Как мы разрабатываем новый фронтенд / Филипп Нехаев (Tinkoff.ru)
Как мы разрабатываем новый фронтенд / Филипп Нехаев (Tinkoff.ru)Как мы разрабатываем новый фронтенд / Филипп Нехаев (Tinkoff.ru)
Как мы разрабатываем новый фронтенд / Филипп Нехаев (Tinkoff.ru)
 
Стабильность WebGL приложений / Кирилл Дмитренко (Яндекс)
Стабильность WebGL приложений / Кирилл Дмитренко (Яндекс)Стабильность WebGL приложений / Кирилл Дмитренко (Яндекс)
Стабильность WebGL приложений / Кирилл Дмитренко (Яндекс)
 
Классические архитектуры во фронтенде / Александра Шинкевич (LOVATA)
Классические архитектуры во фронтенде / Александра Шинкевич (LOVATA)Классические архитектуры во фронтенде / Александра Шинкевич (LOVATA)
Классические архитектуры во фронтенде / Александра Шинкевич (LOVATA)
 
Angular vs Angular 2 vs React. Сергей Александров
Angular vs Angular 2 vs React. Сергей АлександровAngular vs Angular 2 vs React. Сергей Александров
Angular vs Angular 2 vs React. Сергей Александров
 
Радости и гадости регрессионного тестирования вёрстки / Алексей Малейков (HTM...
Радости и гадости регрессионного тестирования вёрстки / Алексей Малейков (HTM...Радости и гадости регрессионного тестирования вёрстки / Алексей Малейков (HTM...
Радости и гадости регрессионного тестирования вёрстки / Алексей Малейков (HTM...
 
Архитектура поиска в Avito / Андрей Смирнов (Avito)
Архитектура поиска в Avito / Андрей Смирнов (Avito)Архитектура поиска в Avito / Андрей Смирнов (Avito)
Архитектура поиска в Avito / Андрей Смирнов (Avito)
 
Использование Tarantool в качестве платформы виртуализации данных / Константи...
Использование Tarantool в качестве платформы виртуализации данных / Константи...Использование Tarantool в качестве платформы виртуализации данных / Константи...
Использование Tarantool в качестве платформы виртуализации данных / Константи...
 
Чему мы научились, разрабатывая микросервисы / Вадим Мадисон (RuTube)
Чему мы научились, разрабатывая микросервисы / Вадим Мадисон (RuTube)Чему мы научились, разрабатывая микросервисы / Вадим Мадисон (RuTube)
Чему мы научились, разрабатывая микросервисы / Вадим Мадисон (RuTube)
 
FrontDays #1. Алексей Ульянов, React.js и методологии разработки на нём
FrontDays #1. Алексей Ульянов, React.js и методологии разработки на нёмFrontDays #1. Алексей Ульянов, React.js и методологии разработки на нём
FrontDays #1. Алексей Ульянов, React.js и методологии разработки на нём
 

More from Ontico

One-cloud — система управления дата-центром в Одноклассниках / Олег Анастасье...
One-cloud — система управления дата-центром в Одноклассниках / Олег Анастасье...One-cloud — система управления дата-центром в Одноклассниках / Олег Анастасье...
One-cloud — система управления дата-центром в Одноклассниках / Олег Анастасье...Ontico
 
Масштабируя DNS / Артем Гавриченков (Qrator Labs)
Масштабируя DNS / Артем Гавриченков (Qrator Labs)Масштабируя DNS / Артем Гавриченков (Qrator Labs)
Масштабируя DNS / Артем Гавриченков (Qrator Labs)Ontico
 
Создание BigData-платформы для ФГУП Почта России / Андрей Бащенко (Luxoft)
Создание BigData-платформы для ФГУП Почта России / Андрей Бащенко (Luxoft)Создание BigData-платформы для ФГУП Почта России / Андрей Бащенко (Luxoft)
Создание BigData-платформы для ФГУП Почта России / Андрей Бащенко (Luxoft)Ontico
 
Готовим тестовое окружение, или сколько тестовых инстансов вам нужно / Алекса...
Готовим тестовое окружение, или сколько тестовых инстансов вам нужно / Алекса...Готовим тестовое окружение, или сколько тестовых инстансов вам нужно / Алекса...
Готовим тестовое окружение, или сколько тестовых инстансов вам нужно / Алекса...Ontico
 
Новые технологии репликации данных в PostgreSQL / Александр Алексеев (Postgre...
Новые технологии репликации данных в PostgreSQL / Александр Алексеев (Postgre...Новые технологии репликации данных в PostgreSQL / Александр Алексеев (Postgre...
Новые технологии репликации данных в PostgreSQL / Александр Алексеев (Postgre...Ontico
 
PostgreSQL Configuration for Humans / Alvaro Hernandez (OnGres)
PostgreSQL Configuration for Humans / Alvaro Hernandez (OnGres)PostgreSQL Configuration for Humans / Alvaro Hernandez (OnGres)
PostgreSQL Configuration for Humans / Alvaro Hernandez (OnGres)Ontico
 
Inexpensive Datamasking for MySQL with ProxySQL — Data Anonymization for Deve...
Inexpensive Datamasking for MySQL with ProxySQL — Data Anonymization for Deve...Inexpensive Datamasking for MySQL with ProxySQL — Data Anonymization for Deve...
Inexpensive Datamasking for MySQL with ProxySQL — Data Anonymization for Deve...Ontico
 
Опыт разработки модуля межсетевого экранирования для MySQL / Олег Брославский...
Опыт разработки модуля межсетевого экранирования для MySQL / Олег Брославский...Опыт разработки модуля межсетевого экранирования для MySQL / Олег Брославский...
Опыт разработки модуля межсетевого экранирования для MySQL / Олег Брославский...Ontico
 
ProxySQL Use Case Scenarios / Alkin Tezuysal (Percona)
ProxySQL Use Case Scenarios / Alkin Tezuysal (Percona)ProxySQL Use Case Scenarios / Alkin Tezuysal (Percona)
ProxySQL Use Case Scenarios / Alkin Tezuysal (Percona)Ontico
 
MySQL Replication — Advanced Features / Петр Зайцев (Percona)
MySQL Replication — Advanced Features / Петр Зайцев (Percona)MySQL Replication — Advanced Features / Петр Зайцев (Percona)
MySQL Replication — Advanced Features / Петр Зайцев (Percona)Ontico
 
Внутренний open-source. Как разрабатывать мобильное приложение большим количе...
Внутренний open-source. Как разрабатывать мобильное приложение большим количе...Внутренний open-source. Как разрабатывать мобильное приложение большим количе...
Внутренний open-source. Как разрабатывать мобильное приложение большим количе...Ontico
 
Подробно о том, как Causal Consistency реализовано в MongoDB / Михаил Тюленев...
Подробно о том, как Causal Consistency реализовано в MongoDB / Михаил Тюленев...Подробно о том, как Causal Consistency реализовано в MongoDB / Михаил Тюленев...
Подробно о том, как Causal Consistency реализовано в MongoDB / Михаил Тюленев...Ontico
 
Балансировка на скорости проводов. Без ASIC, без ограничений. Решения NFWare ...
Балансировка на скорости проводов. Без ASIC, без ограничений. Решения NFWare ...Балансировка на скорости проводов. Без ASIC, без ограничений. Решения NFWare ...
Балансировка на скорости проводов. Без ASIC, без ограничений. Решения NFWare ...Ontico
 
Перехват трафика — мифы и реальность / Евгений Усков (Qrator Labs)
Перехват трафика — мифы и реальность / Евгений Усков (Qrator Labs)Перехват трафика — мифы и реальность / Евгений Усков (Qrator Labs)
Перехват трафика — мифы и реальность / Евгений Усков (Qrator Labs)Ontico
 
И тогда наверняка вдруг запляшут облака! / Алексей Сушков (ПЕТЕР-СЕРВИС)
И тогда наверняка вдруг запляшут облака! / Алексей Сушков (ПЕТЕР-СЕРВИС)И тогда наверняка вдруг запляшут облака! / Алексей Сушков (ПЕТЕР-СЕРВИС)
И тогда наверняка вдруг запляшут облака! / Алексей Сушков (ПЕТЕР-СЕРВИС)Ontico
 
Как мы заставили Druid работать в Одноклассниках / Юрий Невиницин (OK.RU)
Как мы заставили Druid работать в Одноклассниках / Юрий Невиницин (OK.RU)Как мы заставили Druid работать в Одноклассниках / Юрий Невиницин (OK.RU)
Как мы заставили Druid работать в Одноклассниках / Юрий Невиницин (OK.RU)Ontico
 
Разгоняем ASP.NET Core / Илья Вербицкий (WebStoating s.r.o.)
Разгоняем ASP.NET Core / Илья Вербицкий (WebStoating s.r.o.)Разгоняем ASP.NET Core / Илья Вербицкий (WebStoating s.r.o.)
Разгоняем ASP.NET Core / Илья Вербицкий (WebStoating s.r.o.)Ontico
 
100500 способов кэширования в Oracle Database или как достичь максимальной ск...
100500 способов кэширования в Oracle Database или как достичь максимальной ск...100500 способов кэширования в Oracle Database или как достичь максимальной ск...
100500 способов кэширования в Oracle Database или как достичь максимальной ск...Ontico
 
Apache Ignite Persistence: зачем Persistence для In-Memory, и как он работает...
Apache Ignite Persistence: зачем Persistence для In-Memory, и как он работает...Apache Ignite Persistence: зачем Persistence для In-Memory, и как он работает...
Apache Ignite Persistence: зачем Persistence для In-Memory, и как он работает...Ontico
 
Механизмы мониторинга баз данных: взгляд изнутри / Дмитрий Еманов (Firebird P...
Механизмы мониторинга баз данных: взгляд изнутри / Дмитрий Еманов (Firebird P...Механизмы мониторинга баз данных: взгляд изнутри / Дмитрий Еманов (Firebird P...
Механизмы мониторинга баз данных: взгляд изнутри / Дмитрий Еманов (Firebird P...Ontico
 

More from Ontico (20)

One-cloud — система управления дата-центром в Одноклассниках / Олег Анастасье...
One-cloud — система управления дата-центром в Одноклассниках / Олег Анастасье...One-cloud — система управления дата-центром в Одноклассниках / Олег Анастасье...
One-cloud — система управления дата-центром в Одноклассниках / Олег Анастасье...
 
Масштабируя DNS / Артем Гавриченков (Qrator Labs)
Масштабируя DNS / Артем Гавриченков (Qrator Labs)Масштабируя DNS / Артем Гавриченков (Qrator Labs)
Масштабируя DNS / Артем Гавриченков (Qrator Labs)
 
Создание BigData-платформы для ФГУП Почта России / Андрей Бащенко (Luxoft)
Создание BigData-платформы для ФГУП Почта России / Андрей Бащенко (Luxoft)Создание BigData-платформы для ФГУП Почта России / Андрей Бащенко (Luxoft)
Создание BigData-платформы для ФГУП Почта России / Андрей Бащенко (Luxoft)
 
Готовим тестовое окружение, или сколько тестовых инстансов вам нужно / Алекса...
Готовим тестовое окружение, или сколько тестовых инстансов вам нужно / Алекса...Готовим тестовое окружение, или сколько тестовых инстансов вам нужно / Алекса...
Готовим тестовое окружение, или сколько тестовых инстансов вам нужно / Алекса...
 
Новые технологии репликации данных в PostgreSQL / Александр Алексеев (Postgre...
Новые технологии репликации данных в PostgreSQL / Александр Алексеев (Postgre...Новые технологии репликации данных в PostgreSQL / Александр Алексеев (Postgre...
Новые технологии репликации данных в PostgreSQL / Александр Алексеев (Postgre...
 
PostgreSQL Configuration for Humans / Alvaro Hernandez (OnGres)
PostgreSQL Configuration for Humans / Alvaro Hernandez (OnGres)PostgreSQL Configuration for Humans / Alvaro Hernandez (OnGres)
PostgreSQL Configuration for Humans / Alvaro Hernandez (OnGres)
 
Inexpensive Datamasking for MySQL with ProxySQL — Data Anonymization for Deve...
Inexpensive Datamasking for MySQL with ProxySQL — Data Anonymization for Deve...Inexpensive Datamasking for MySQL with ProxySQL — Data Anonymization for Deve...
Inexpensive Datamasking for MySQL with ProxySQL — Data Anonymization for Deve...
 
Опыт разработки модуля межсетевого экранирования для MySQL / Олег Брославский...
Опыт разработки модуля межсетевого экранирования для MySQL / Олег Брославский...Опыт разработки модуля межсетевого экранирования для MySQL / Олег Брославский...
Опыт разработки модуля межсетевого экранирования для MySQL / Олег Брославский...
 
ProxySQL Use Case Scenarios / Alkin Tezuysal (Percona)
ProxySQL Use Case Scenarios / Alkin Tezuysal (Percona)ProxySQL Use Case Scenarios / Alkin Tezuysal (Percona)
ProxySQL Use Case Scenarios / Alkin Tezuysal (Percona)
 
MySQL Replication — Advanced Features / Петр Зайцев (Percona)
MySQL Replication — Advanced Features / Петр Зайцев (Percona)MySQL Replication — Advanced Features / Петр Зайцев (Percona)
MySQL Replication — Advanced Features / Петр Зайцев (Percona)
 
Внутренний open-source. Как разрабатывать мобильное приложение большим количе...
Внутренний open-source. Как разрабатывать мобильное приложение большим количе...Внутренний open-source. Как разрабатывать мобильное приложение большим количе...
Внутренний open-source. Как разрабатывать мобильное приложение большим количе...
 
Подробно о том, как Causal Consistency реализовано в MongoDB / Михаил Тюленев...
Подробно о том, как Causal Consistency реализовано в MongoDB / Михаил Тюленев...Подробно о том, как Causal Consistency реализовано в MongoDB / Михаил Тюленев...
Подробно о том, как Causal Consistency реализовано в MongoDB / Михаил Тюленев...
 
Балансировка на скорости проводов. Без ASIC, без ограничений. Решения NFWare ...
Балансировка на скорости проводов. Без ASIC, без ограничений. Решения NFWare ...Балансировка на скорости проводов. Без ASIC, без ограничений. Решения NFWare ...
Балансировка на скорости проводов. Без ASIC, без ограничений. Решения NFWare ...
 
Перехват трафика — мифы и реальность / Евгений Усков (Qrator Labs)
Перехват трафика — мифы и реальность / Евгений Усков (Qrator Labs)Перехват трафика — мифы и реальность / Евгений Усков (Qrator Labs)
Перехват трафика — мифы и реальность / Евгений Усков (Qrator Labs)
 
И тогда наверняка вдруг запляшут облака! / Алексей Сушков (ПЕТЕР-СЕРВИС)
И тогда наверняка вдруг запляшут облака! / Алексей Сушков (ПЕТЕР-СЕРВИС)И тогда наверняка вдруг запляшут облака! / Алексей Сушков (ПЕТЕР-СЕРВИС)
И тогда наверняка вдруг запляшут облака! / Алексей Сушков (ПЕТЕР-СЕРВИС)
 
Как мы заставили Druid работать в Одноклассниках / Юрий Невиницин (OK.RU)
Как мы заставили Druid работать в Одноклассниках / Юрий Невиницин (OK.RU)Как мы заставили Druid работать в Одноклассниках / Юрий Невиницин (OK.RU)
Как мы заставили Druid работать в Одноклассниках / Юрий Невиницин (OK.RU)
 
Разгоняем ASP.NET Core / Илья Вербицкий (WebStoating s.r.o.)
Разгоняем ASP.NET Core / Илья Вербицкий (WebStoating s.r.o.)Разгоняем ASP.NET Core / Илья Вербицкий (WebStoating s.r.o.)
Разгоняем ASP.NET Core / Илья Вербицкий (WebStoating s.r.o.)
 
100500 способов кэширования в Oracle Database или как достичь максимальной ск...
100500 способов кэширования в Oracle Database или как достичь максимальной ск...100500 способов кэширования в Oracle Database или как достичь максимальной ск...
100500 способов кэширования в Oracle Database или как достичь максимальной ск...
 
Apache Ignite Persistence: зачем Persistence для In-Memory, и как он работает...
Apache Ignite Persistence: зачем Persistence для In-Memory, и как он работает...Apache Ignite Persistence: зачем Persistence для In-Memory, и как он работает...
Apache Ignite Persistence: зачем Persistence для In-Memory, и как он работает...
 
Механизмы мониторинга баз данных: взгляд изнутри / Дмитрий Еманов (Firebird P...
Механизмы мониторинга баз данных: взгляд изнутри / Дмитрий Еманов (Firebird P...Механизмы мониторинга баз данных: взгляд изнутри / Дмитрий Еманов (Firebird P...
Механизмы мониторинга баз данных: взгляд изнутри / Дмитрий Еманов (Firebird P...
 

Angular 2 не так уж и плох... А если задуматься, то и просто хорош / Алексей Охрименко (IPONWEB)

  • 1. Angular 2 не так уж и плох, а если задуматься то и просто хорош. Алексей Охрименко ( IPONWEB ) 1
  • 5. 5 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!'; }
  • 6. 6 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!'; }
  • 7. 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. Глава №1 - И была рука 8
  • 13. Глава №2 - Горы отвращения 13
  • 14. Angular 2 is Beta* 14 * - now RC1
  • 15. ASP.Net MVC - Developer Preview 2 15
  • 16. 16
  • 17. 17 ([]) [] () ([]) [] () ([]) [] ([]) [] () ([] ([]) [] ([]) [] () ([])
  • 18. 18
  • 19. 19 /** * Simplest possible template in AngularJs-ISH style * * @param {String} template - template string * @param {Object} ctx - template context * @param {Object} eventHandlerObject - object that will be used as "this" in event handling * @returns {Node} returns dom node element */ export default function angularish(template, ctx, eventHandlerObject) { var node; var container = document.createElement('div'); container.innerHTML = template; var walker = document.createTreeWalker(container, NodeFilter.SHOW_ELEMENT, null, false); while (node = walker.nextNode()) { // inheritance of context node.ctx = node.ctx || node.parentNode.ctx || ctx; // ng-scope allows you to change scope of the node (new scope can be any property of old scope) if (node.getAttribute('ng-scope')) { node.ctx = _getValue(node.ctx, node.getAttribute('ng-scope')); } // ng-loop will repeat first child (TODO: reapeat content) and assign correct context if (node.getAttribute('ng-loop')) {
  • 20. 20 /** * Simplest possible template in AngularJs-ISH style * * @param {String} template - template string * @param {Object} ctx - template context * @param {Object} eventHandlerObject - object that will be used as "this" in event handling * @returns {Node} returns dom node element */ export default function angularish(template, ctx, eventHandlerObject) { var node; var container = document.createElement('div'); container.innerHTML = template; var walker = document.createTreeWalker(container, NodeFilter.SHOW_ELEMENT, null, false); while (node = walker.nextNode()) { // inheritance of context node.ctx = node.ctx || node.parentNode.ctx || ctx; // ng-scope allows you to change scope of the node (new scope can be any property of old scope) if (node.getAttribute('ng-scope')) { node.ctx = _getValue(node.ctx, node.getAttribute('ng-scope')); } // ng-loop will repeat first child (TODO: reapeat content) and assign correct context if (node.getAttribute('ng-loop')) {
  • 21. 21 /** * Simplest possible template in AngularJs-ISH style * * @param {String} template - template string * @param {Object} ctx - template context * @param {Object} eventHandlerObject - object that will be used as "this" in event handling * @returns {Node} returns dom node element */ export default function angularish(template, ctx, eventHandlerObject) { var node; var container = document.createElement('div'); container.innerHTML = template; var walker = document.createTreeWalker(container, NodeFilter.SHOW_ELEMENT, null, false); while (node = walker.nextNode()) { // inheritance of context node.ctx = node.ctx || node.parentNode.ctx || ctx; // ng-scope allows you to change scope of the node (new scope can be any property of old scope) if (node.getAttribute('ng-scope')) { node.ctx = _getValue(node.ctx, node.getAttribute('ng-scope')); } // ng-loop will repeat first child (TODO: reapeat content) and assign correct context if (node.getAttribute('ng-loop')) {
  • 22. 22 node.value = _getValue(node.ctx, node.getAttribute('ng-value')); } // ng-selected will set selected attribute depending on true-finess of value if (node.getAttribute('ng-selected')) { var selected = _getValue(node.ctx, node.getAttribute('ng-selected')); if (selected) { node.setAttribute('selected', 'yes'); } } // ng-text will assign text to node no need for escaping if (node.getAttribute('ng-text')) { node.innerText = _getValue(node.ctx, node.getAttribute('ng-text')); } // ng-class will simply assign class from defined property if (node.getAttribute('ng-class')) { var classVal = _getValue(node.ctx, node.getAttribute('ng-class')); if (classVal) { node.className += ' ' + classVal; } } // ng-show shows elements depending on true-finess of the value if (node.getAttribute('ng-show')) {
  • 23. 23 // ng-scope allows you to change scope of the node (new scope can be any property of old scope) if (node.getAttribute('ng-scope')) { node.ctx = _getValue(node.ctx, node.getAttribute('ng-scope')); } // ng-loop will repeat first child (TODO: reapeat content) and assign correct context if (node.getAttribute('ng-loop')) { var child = node.children[0]; var array = _getValue(node.ctx, node.getAttribute('ng-loop')) || []; node.removeChild(child); array.forEach((item) => { child = child.cloneNode(true); child.ctx = item; node.appendChild(child); }); } // ng-value will assign value to node if (node.getAttribute('ng-value')) { node.value = _getValue(node.ctx, node.getAttribute('ng-value')); } // ng-selected will set selected attribute depending on true-finess of value if (node.getAttribute('ng-selected')) {
  • 24. 24 // ng-change will add "change" event handler if (node.getAttribute('ng-change')) { // closure to rescue ((node)=> { node.addEventListener('change', (event) => { eventHandlerObject[node.getAttribute(‘ng-change')] .bind(eventHandlerObject)(node.ctx, event); }, true); })(node); } // ng-click will add "click" event handler if (node.getAttribute('ng-click')) { // closure to rescue ((node)=> { node.addEventListener('click', (event) => { eventHandlerObject[node.getAttribute(‘ng-click')] .bind(eventHandlerObject)(node.ctx, event); }, true); })(node); } } return container; } function _getValue(ctx, attrVal) { if (attrVal === 'self') { return ctx; }
  • 25. 25 } // ng-hide shows elements depending on false-iness of the value if (node.getAttribute('ng-hide')) { var isHidden = _getValue(node.ctx, node.getAttribute('ng-hide')); if (isHidden) { node.style.display = 'none'; } } // ng-change will add "change" event handler if (node.getAttribute('ng-change')) { // closure to rescue ((node)=> { node.addEventListener('change', (event) => { eventHandlerObject[node.getAttribute(‘ng-change')] .bind(eventHandlerObject)(node.ctx, event); }, true); })(node); } // ng-click will add "click" event handler if (node.getAttribute('ng-click')) { // closure to rescue ((node)=> { node.addEventListener('click', (event) => { eventHandlerObject[node.getAttribute(‘ng-click')] .bind(eventHandlerObject)(node.ctx, event); }, true); })(node); }
  • 29. 29 [property]=‘value’ -> property=‘value’ (event)=‘handler()’ -> on-event=‘handler()’ [(target)]=‘value’ -> on-change=‘update()’ -> target=‘value’
  • 30. 30 bind-property=‘value’ -> property=‘value’ (event)=‘handler()’ -> on-event=‘handler()’ [(target)]=‘value’ -> on-change=‘update()’ -> target=‘value’
  • 31. 31 bind-property=‘value’ -> property=‘value’ on-event=‘handler()’ -> on-event=‘handler()’ [(target)]=‘value’ -> on-change=‘update()’ -> target=‘value’
  • 32. 32 bind-property=‘value’ -> property=‘value’ on-event=‘handler()’ -> on-event=‘handler()’ bindon-prop=‘value’ -> on-change=‘update()’ -> target=‘value’
  • 36. System.js & JSPM & System.js Builder 36 http://plnkr.co/
  • 37. System.js & JSPM & System.js Builder 37 <title>angular2 playground</title> <link rel="stylesheet" href="style.css" /> <script src="https://code.angularjs.org/2.0.0-beta.17/ angular2-polyfills.js"></script> <script src="https://code.angularjs.org/tools/system.js"></ script> <script src="https://code.angularjs.org/tools/ typescript.js"></script> <script src="config.js"></script> <script> System.import('app') .catch(console.error.bind(console)); </script> </head>
  • 38. System.js & JSPM & System.js Builder 38 <title>angular2 playground</title> <link rel="stylesheet" href="style.css" /> <script src="https://code.angularjs.org/2.0.0-beta.17/ angular2-polyfills.js"></script> <script src="https://code.angularjs.org/tools/system.js"></ script> <script src="https://code.angularjs.org/tools/ typescript.js"></script> <script src="config.js"></script> <script> System.import('app') .catch(console.error.bind(console)); </script> </head>
  • 39. 39 System.config({ //use typescript for compilation transpiler: 'typescript', //typescript compiler options typescriptOptions: { emitDecoratorMetadata: true }, //map tells the System loader where to look for things map: { app: "./src", '@angular': 'https://npmcdn.com/@angular', 'rxjs': 'https://npmcdn.com/rxjs@5.0.0-beta.6' }, //packages defines our app package packages: { app: { main: './main.ts', defaultExtension: 'ts' }, '@angular/core': { main: 'core.umd.js', defaultExtension: 'js' }, '@angular/compiler': { main: 'compiler.umd.js', defaultExtension: 'js' }, '@angular/common': { main: 'common.umd.js', defaultExtension: 'js' }, '@angular/platform-browser-dynamic': { main: 'platform-browser-dynamic.umd.js', defaultExtension: 'js' }, '@angular/platform-browser': { main: 'platform-browser.umd.js', defaultExtension: 'js' }, rxjs: { defaultExtension: 'js' } } });
  • 40. 40 System.config({ //use typescript for compilation transpiler: 'typescript', //typescript compiler options typescriptOptions: { emitDecoratorMetadata: true }, //map tells the System loader where to look for things map: { app: "./src", '@angular': 'https://npmcdn.com/@angular', 'rxjs': 'https://npmcdn.com/rxjs@5.0.0-beta.6' }, //packages defines our app package packages: { app: { main: './main.ts', defaultExtension: 'ts' }, '@angular/core': { main: 'core.umd.js', defaultExtension: 'js' }, '@angular/compiler': { main: 'compiler.umd.js', defaultExtension: 'js' }, '@angular/common': { main: 'common.umd.js', defaultExtension: 'js' }, '@angular/platform-browser-dynamic': { main: 'platform-browser-dynamic.umd.js', defaultExtension: 'js' }, '@angular/platform-browser': { main: 'platform-browser.umd.js', defaultExtension: 'js' }, rxjs: { defaultExtension: 'js' } } }); 44 строчки конфига
  • 41. Не хуже чем Webpack • Официальный Angular QuickStart репозиторий • Angular CLI • Yoman / Slush - генераторы
  • 45. TypeScript 45 • .Net, Java, Scala background • SOLID, Design Patterns • 1.8.10 • Poor documentation - «google search ftw»
  • 46. Глава №3 - Добыча 46
  • 47. Размер 47 Development Production Size in KB 0 50 100 150 200 250 300 350 400 React Angular 1 Angular 2
  • 48. Размер - Angular 2 Router 48
  • 49. Размер - Angular 2 Router 49
  • 50. Размер - Angular 2 Router 50
  • 51. CSS 51 import {Component} from '@angular/core' @Component({ selector: 'my-app', providers: [], styles: [` h2 { color: red; } `], template: ` <div> <h2>Hello {{name}}</h2> </div> `, directives: [] }) export class App { constructor() { this.name = 'Angular2 (Release Candidate!)' } }
  • 52. CSS 52 import {Component} from '@angular/core' @Component({ selector: 'my-app', providers: [], styles: [` body { color: red; } `], template: ` <div> <h2>Hello {{name}}</h2> </div> `, directives: [] }) export class App { constructor() { this.name = 'Angular2 (Release Candidate!)' } }
  • 55. 55 import { Component } from '@angular/core'; @Component({ moduleId: module.id, selector: 'project-name-app', template: ` <h1> {{title}} </h1> `, styleUrls: ['project-name.component.css'] }) export class PROJECTNAMEAppComponent { title = 'project-name works!'; }
  • 56. 56 new jit_StaticNodeDebugInfo0([],null,{}), new jit_StaticNodeDebugInfo0([],null,{}), new jit_StaticNodeDebugInfo0([],null,{}) ] ; var renderType_PROJECTNAMEAppComponent = null; function _View_PROJECTNAMEAppComponent0(viewUtils,parentInjector,declarationEl) { var self = this; jit_DebugAppView1.call(this, _View_PROJECTNAMEAppComponent0,renderType_PROJECTNAMEAppComponent,jit_ViewType_COMPONENT2,viewUtils,parentInjec rationEl,jit_ChangeDetectionStrategy_CheckAlways3,nodeDebugInfos_PROJECTNAMEAppComponent0); } _View_PROJECTNAMEAppComponent0.prototype = Object.create(jit_DebugAppView1.prototype); _View_PROJECTNAMEAppComponent0.prototype.createInternal = function(rootSelector) { var self = this; var parentRenderNode = self.renderer.createViewRoot(self.declarationAppElement.nativeElement); self._el_0 = self.renderer.createElement(parentRenderNode,'h1',self.debug(0,0,0)); self._text_1 = self.renderer.createText(self._el_0,'',self.debug(1,0,4)); self._text_2 = self.renderer.createText(parentRenderNode,'n',self.debug(2,2,5)); self._expr_0 = jit_uninitialized4; self.init([],[ self._el_0, self._text_1, self._text_2 ] ,[],[]); return null; }; _View_PROJECTNAMEAppComponent0.prototype.detectChangesInternal = function(throwOnChange) { var self = this; self.detectContentChildrenChanges(throwOnChange); self.debug(1,0,4);
  • 57. 57 new jit_StaticNodeDebugInfo0([],null,{}), new jit_StaticNodeDebugInfo0([],null,{}), new jit_StaticNodeDebugInfo0([],null,{}) ] ; var renderType_PROJECTNAMEAppComponent = null; function _View_PROJECTNAMEAppComponent0(viewUtils,parentInjector,declarationEl) { var self = this; jit_DebugAppView1.call(this, _View_PROJECTNAMEAppComponent0,renderType_PROJECTNAMEAppComponent,jit_ViewType_COMPONENT2,viewUtils,parentInjec rationEl,jit_ChangeDetectionStrategy_CheckAlways3,nodeDebugInfos_PROJECTNAMEAppComponent0); } _View_PROJECTNAMEAppComponent0.prototype = Object.create(jit_DebugAppView1.prototype); _View_PROJECTNAMEAppComponent0.prototype.createInternal = function(rootSelector) { var self = this; var parentRenderNode = self.renderer.createViewRoot(self.declarationAppElement.nativeElement); self._el_0 = self.renderer.createElement(parentRenderNode,'h1',self.debug(0,0,0)); self._text_1 = self.renderer.createText(self._el_0,'',self.debug(1,0,4)); self._text_2 = self.renderer.createText(parentRenderNode,'n',self.debug(2,2,5)); self._expr_0 = jit_uninitialized4; self.init([],[ self._el_0, self._text_1, self._text_2 ] ,[],[]); return null; }; _View_PROJECTNAMEAppComponent0.prototype.detectChangesInternal = function(throwOnChange) { var self = this; self.detectContentChildrenChanges(throwOnChange); self.debug(1,0,4);
  • 60. Speed immutability 60 import { Component, Pipe, PipeTransform } from '@angular/core'; @Pipe({ name: 'isOdd' }) export class IsOddPipe implements PipeTransform { transform(array:any[]) { return array.filter(item => item.isOdd); } } @Component({ moduleId: module.id, selector: 'project-name-app', pipes: [IsOddPipe], template: ` <button (click)="add()">add</button> <div> <div *ngFor="let item of list | isOdd"> {{ item.name }} </div> </div> `, styleUrls: ['project-name.component.css'] }) export class PROJECTNAMEAppComponent { list = [] add() { this.list.push({ name: ‘test', isOdd: !!(this.list.length % 2) }) } }
  • 61. Speed immutability 61 import { Component, Pipe, PipeTransform } from '@angular/core'; @Pipe({ name: 'isOdd' }) export class IsOddPipe implements PipeTransform { transform(array:any[]) { return array.filter(item => item.isOdd); } } @Component({ moduleId: module.id, selector: 'project-name-app', pipes: [IsOddPipe], template: ` <button (click)="add()">add</button> <div> <div *ngFor="let item of list | isOdd"> {{ item.name }} </div> </div> `, styleUrls: ['project-name.component.css'] }) export class PROJECTNAMEAppComponent { list = [] add() { this.list.push({ name: ‘test', isOdd: !!(this.list.length % 2) }) } }
  • 62. Speed immutability 62 import { Component, Pipe, PipeTransform } from '@angular/core'; @Pipe({ name: 'isOdd' }) export class IsOddPipe implements PipeTransform { transform(array:any[]) { return array.filter(item => item.isOdd); } } @Component({ moduleId: module.id, selector: 'project-name-app', pipes: [IsOddPipe], template: ` <button (click)="add()">add</button> <div> <div *ngFor="let item of list | isOdd"> {{ item.name }} </div> </div> `, styleUrls: ['project-name.component.css'] }) export class PROJECTNAMEAppComponent { list = [] add() { this.list.push({ name: ‘test', isOdd: !!(this.list.length % 2) }) } }
  • 63. Speed immutability 63 import { Component, Pipe, PipeTransform } from '@angular/core'; @Pipe({ name: ‘isOdd’, is_pure: false }) export class IsOddPipe implements PipeTransform { transform(array:any[]) { return array.filter(item => item.isOdd); } } @Component({ moduleId: module.id, selector: 'project-name-app', pipes: [IsOddPipe], template: ` <button (click)="add()">add</button> <div> <div *ngFor="let item of list | isOdd"> {{ item.name }} </div> </div> `, styleUrls: ['project-name.component.css'] }) export class PROJECTNAMEAppComponent { list = [] add() { this.list.push({ name: ‘test', isOdd: !!(this.list.length % 2) }) } }
  • 64. Speed immutability 64 import { Component, Pipe, PipeTransform } from '@angular/core'; @Pipe({ name: 'isOdd' }) export class IsOddPipe implements PipeTransform { transform(array:any[]) { return array.filter(item => item.isOdd); } } @Component({ moduleId: module.id, selector: 'project-name-app', pipes: [IsOddPipe], template: ` <button (click)="add()">add</button> <div> <div *ngFor="let item of list | isOdd"> {{ item.name }} </div> </div> `, styleUrls: ['project-name.component.css'] }) export class PROJECTNAMEAppComponent { list = [] add() { this.list = this.list.splice().filter((i) => i % 2) }) } }
  • 65. Speed - zone.js 65 Zone.fork().run(function () { zone.inTheZone = true; setTimeout(function () { console.log('in the zone: ' + !!zone.inTheZone); }, 0); }); console.log('in the zone: ' + !!zone.inTheZone); ————————————————————————————— 'in the zone: false' 'in the zone: true'
  • 66. Speed - zone.js 66 Zone.fork().run(function () { zone.inTheZone = true; setTimeout(function () { console.log('in the zone: ' + !!zone.inTheZone); }, 0); }); console.log('in the zone: ' + !!zone.inTheZone); ————————————————————————————— 'in the zone: false' 'in the zone: true'
  • 67. TypeScript OOP 67 class GenericService<T> { items: Array<T> = [] addItem(item: T) { this.items.push(item) } } interface User { id: number, name: string } interface Creatives { type: string, value: string }
  • 68. TypeScript OOP 68 var s = new GenericService<User>(); s.addItem({ id: 1, name: 'asda' }); s.addItem({ type: ‘asda' // will fail })
  • 69. Глава №4 - Первые потери 69 … а вот этого я не ожидал
  • 70. Потеря почти всей кодовой базы 70
  • 73. Promise -> RXJS 73 import {Http, HTTP_PROVIDERS} from 'angular2/http'; @Component({ selector: 'http-app', viewProviders: [HTTP_PROVIDERS], templateUrl: 'people.html' }) class PeopleComponent { constructor(http: Http) { http.get('people.json') .map(res => res.json()) .subscribe(people => this.people = people); } }
  • 74. Promise -> RXJS 74 import {Http, HTTP_PROVIDERS} from 'angular2/http'; @Component({ selector: 'http-app', viewProviders: [HTTP_PROVIDERS], templateUrl: 'people.html' }) class PeopleComponent { constructor(http: Http) { http.get('people.json') .map(res => res.json()) .subscribe(people => this.people = people); } }
  • 75. Promise -> RXJS 75 import {Http, HTTP_PROVIDERS} from 'angular2/http'; @Component({ selector: 'http-app', viewProviders: [HTTP_PROVIDERS], templateUrl: 'people.html' }) class PeopleComponent { constructor(http: Http) { http.get('people.json') .map(res => res.json()) .subscribe(people => this.people = people); } }
  • 77. RXJS 77 interface IObservable<T> { IDisposable Subscribe(IObserver observer); } interface IObserver<T> { void OnCompleted(); void OnNext(T value); void OnError(Exception e); }
  • 78. ngResources 78 var User = $resource('/user/:userId', {userId:'@id'}); User.get({userId:123}, function(user) { user.abc = true; user.$save(); });
  • 79. ngResources 79 var User = $resource('/user/:userId', {userId:'@id'}); User.get({userId:123}, function(user) { user.abc = true; user.$save(); });
  • 80. Встроенные паттерны канули в небытие! 80 1) component 2) directive 3) filter 4) service 5) provider 6) constant 7) config 8) run 9) module
  • 81. Встроенные паттерны канули в небытие! 81 1) component 2) template 3) directive 4) route 5) pipe 6) service *
  • 83. Формы 83 1) [(ngModel)] 2) ng-valid | ng-invalid | ng-dirty | ng-pristine | ng-touched | ng-untouched
  • 84. Формы 84 1) [(ngModel)] 2) ng-valid | ng-invalid | ng-dirty | ng-pristine | ng-touched | ng-untouched 3) FormModel + FormBuilder
  • 85. Формы 85 1) [(ngModel)] 2) ng-valid | ng-invalid | ng-dirty | ng-pristine | ng-touched | ng-untouched 3) FormModel + FormBuilder 4) Валидация не стала легче
  • 86. Глава №5 - Happy End 86
  • 87. Мы уже переехали на Angular 2? 87
  • 89. Почему? 89 1) Потому что Angular 1 не так уж и плох, а если задуматься …
  • 90. Почему? 90 1) Потому что Angular 1 не так уж и плох, а если задуматься … 2) Потому что React 15 не так уж и плох, а если задуматься …
  • 91. Почему? 91 1) Потому что Angular 1 не так уж и плох, а если задуматься … 2) Потому что React 15 не так уж и плох, а если задуматься … 3) Потому что Ember не так уж и плох, а если задуматься …
  • 92. Почему? 92 1) Кодовая база 2) Уровень вхождения 3) Незаконченность*
  • 93. Почему? 93 1) Кодовая база 2) Уровень вхождения 3) Незаконченность*
  • 95. Наши шаги 95 1) TypeScript OOP - e2e tests 2) Angular 1.4.x -> 1.5.x 3) AutoNgConverter
  • 96. О чем мы не поговорили? 96
  • 97. 97 Progressive Web Apps Native - Ionic Framework, - NativeScript - React Native. Desktop - Electron Universal - node.js, - .NET, - PHP Dependency Injection Angular CLI IDEs Testing - patched Karma, Protractor Animation Accessibility Developer Tools
  • 98. 98 -Redux ( ngrx / ng2-redux ) -FLUX -MV* ( MVC, MVP, MVVM ) -MALEVICH ( COD.js )