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 name const x = "valid"; // error, const x = "bar"; } // error, already declared in block let 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 1000 if (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 Data structures List, Map, Set, Records etc. Sequences Convertion from/to objects var map1: Immutable.Map<string, number>; map1 = Immutable.Map({ foo: 1, bar: 2, baz: 3 }); var map2 = map1.set('bar', 25); map1.get('bar'); // 2 map2.get('bar'); // 25
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 System arkitektur Components Komposition / DI Services Interaction og rendering Views Data Binding
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);
Components class 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 christian@dotnetnerd.dk • SPA architecture and patterns www.dotnetnerd.dk • A glimpse into Angular 2.0 @dotnetnerd
Recommend
More recommend