single page applikationer med typescript...types •null, string, number, boolean, undefined...
TRANSCRIPT
TypeScript ❤- a look at SPA's and Angular 2
Christian Holm Diget
Agenda
• EcmaScript 6
• TypeScript
• Libraries: ImmutableJS + React
• SPA architecture
• Angular 2.0
EcmaScript 6/2015
Let + const
function f() {{
let x;{
// okay, block scoped nameconst x = "valid";// error, constx = "bar";
}// error, already declared in blocklet x = "inner";
}}
Arrow functions
var self = this;$('body').on('click', 'a', function(e) {
//self});
$('body').on('click', 'a', e => {//this
});
for…of
for (var n of fibonacci) {// stop at 1000if (n > 1000)
break;console.log(n);
}
Template strings
var car = "Porche", feeling = "awesome";`My ${car} is making me feel ${feeling}!`
Default arguments
function f(x, y = 100) {return x + y;
}
Rest
function f(x, ...y) {return x * y.length;
}
f(100, "volvo", true);
Spread
function addThree(x, y, z) {return x + y + z;
}
addThree(...[100, 50, 25]);
Destructuring
var [a, , b] = [6, 12, 18];
var {name, cylinders, color} = {name: "Audi", cylinders: 8, color: "black"};
Modules
export function fiat() { return "Fiat" }export function peugeot() { return "Peugeot" }
import * as Cars from "my/cars";import { fiat, peugeot } from "my/cars";
Classes
class Ferrari extends Car {constructor(cylinders, color) {
super(cylinders, color);
this.color = color;}start() {
super.start();}static race(cars) {
cars.forEach(car =>car.start()
);}
}
TypeScript
• Superset af JavaScript
• Brug ES6 features og compile til ES3 eller ES5
• Static type checking
• Interfaces
• Generics
• Tooling
Types
• Null, string, number, boolean, undefined• Object, array• Interface, Class, Enum, Any
function ToString(name: string, age: number) : string {return name + age;
};
Default and optional
function ToString(firstName : string = "John Doe", lastName?: string): string {if (lastName) {
return firstName + " " + lastName;}return firstName;
};
Classes
class Person {public age: number;
constructor(public name: string, ageParam: number) {this.age = ageParam;
}
public ToString() : string {return this.name + this.age;
}}
Generics
class Collection<T>{
private items: Array<T>;
public Add(item: T) {this.items.push(item);
}}
Interfaces
interface IPrintable {ToString() : string;
}
class Person implements IPrintable {public age: number;
constructor(public name: string, ageParam: number) {this.age = ageParam;
}
public ToString() : string {return this.name + this.age;
}}
Definitions
• https://github.com/borisyankov/DefinitelyTyped
declare function domready(callback: () => any): void;
declare module "domready" {export = domready;
}
Adoption
ImmutableJS
var map1: Immutable.Map<string, number>;map1 = Immutable.Map({ foo: 1, bar: 2, baz: 3 });var map2 = map1.set('bar', 25);map1.get('bar'); // 2map2.get('bar'); // 25
Data structuresList, Map, Set, Records etc.
SequencesConvertion from/to objects
Sequences
Immutable.Range(1, Infinity).skip(1000).map(n => -n).filter(n => n % 2 === 0).take(2).reduce((r, n) => r * n, 1);
React
TS 1.6 comes with JSX support (tsx)
var HelloWorld = React.createClass({render: function () {
return <div>Hello {this.props.name } </div>;}
});
React.render(<HelloWorld name="John" />, mountNode);
Single Page Application Architektur
Services
Components
Komposition / DI
Data
Views
Binding
Interaction og rendering
System arkitektur
Libraries vs frameworks
1. Build small components
2. Composition over inheritence
3. Loose coupling, high cohesion
Application architecture
Services
export class CarService {
public doStuff(car : Car) {...
}}
Composition with SystemJS
/* Configure */System.config({
baseURL: '/lib/',paths: {
'*': '*.js'}
});
System.import('app');
/* Use in App.js */var carFactory = require('./cars').carFactory;
var audi = carFactory("Audi", 8);
Componentsclass ProductWidget {
constructor(private el: HTMLElement, private product: Product) { }
public Render() {var output = Mustache.render(
'Navn: {{product.name}} ' +'Beskrivelse: {{product.description}}',product);
this.el.innerHTML = output;}
public SetPrice(price: number) { ... }};
new ProductWidget(document.getElementById("prod1"),new Product("Red Bull", "Gi’r vinger", 20));
View rendering
Templates with Mustache
var model = {cars: [
{ make: "Audi", model: "A1" },{ make: "Chevrolet", model: "Aveo" }
]};
var output = Mustache.render('{{#cars}}<tr><td>{{make}}</td><td>{{model}}</td></tr>{{/cars}}',model);
document.getElementById("demo").innerHTML = output;
Data… Routing, validation etc.
Q.xhr.get('/api/products').done((response) => {...
});
Angular 2.0 alpha
• Mobile first
• 5x faster according to google
• Fewer concepts
• Based on webstandards
• AtScript -> TypeScript
• angular.io
• angular-tips.com
Angular 2 languages
• ES5, ES6
• TypeScript
• Dart
Dependencies
• traceur-runtime.js (transpiler)
• system.js (dynamic module loader)
• angular2.d.ts
• rx.d.ts
• es6-promise.d.ts
• https://code.angularjs.org/2.0.0-alpha.37/angular2.dev.js
Annotations
@Component({selector: 'mywidget‘
})@View({
template:'<div *for="#element in elements">{{element.someProperty}}</div>',directives: [For]
})
View Syntax
• Interpolation: {{ expression | pipe }}
• Variable: #variable
• Event bindings: (click) = ""
• Property bindings: [hidden] = ""
• Template directive: *ng-for, *ng-if
Components
• Application = tree of components
@Component({selector: 'mywidget'
})@View({
template:'<div *ng-for="#element in elements">{{element.someProperty}}</div>',directives: [NgFor]
})class MyWidget {
constructor(myService: MyService){ … }
}
Dependency Injection
import {CarService} from 'carService';
@Component({selector: 'carwidget'
})@View({…})class CarWidget {
constructor(carService: CarService) {…}}
Takeaways
• EcmaScript 6
• …and how to use it today
• TypeScript
• ImmutableJS
• SPA architecture and patterns
• A glimpse into Angular 2.0
www.dotnetnerd.dk
@dotnetnerd